This notebook provides the analysis regarding Hypothesis 1, Prediction 1b for the article: Heyne, M., Derrick, D., and Al-Tamimi, J. (under review). “Native language influence on brass instrument performance: An application of generalized additive mixed models (GAMMs) to midsagittal ultrasound images of the tongue”. Frontiers Research Topic: Models and Theories of Speech Production. Ed. Adamantios Gafos & Pascal van Lieshout.

# specify directory to save models and summaries
output_dir = "updated_models"
# specify whether to run models -> if set to false script will attempt to load saved models from output_dir
run_models = FALSE

1 Loading packages

load_packages = c("parallel","mgcv", "itsadug", "rlist", "ggplot2", "plotly", "dplyr")
for(pkg in load_packages){
  eval(bquote(library(.(pkg))))
  if (paste0("package:", pkg) %in% search()){
    cat(paste0("Successfully loaded the ", pkg, " package.\n"))
  }else{
    install.packages(pkg)
    eval(bquote(library(.(pkg))))
    if (paste0("package:", pkg) %in% search()){
      cat(paste0("Successfully loaded the ", pkg, " package.\n"))
    }
  }
}
Successfully loaded the parallel package.
Successfully loaded the mgcv package.
Successfully loaded the itsadug package.
Successfully loaded the rlist package.
Successfully loaded the ggplot2 package.
Successfully loaded the plotly package.
Successfully loaded the dplyr package.
rm(load_packages, pkg)
# detect number of cores available for model calculations
ncores = detectCores()
cat(paste0("Number of cores available for model calculations set to ", ncores, "."))
Number of cores available for model calculations set to 8.

1.0.1 plotly_model_outputs function (Matthias Heyne, 2019)

# plot multiple GAM model outputs
plotly_model_outputs <- function(model, changing_cond, changing_var, constant_cond1, constant_var1, values, constant_cond2=NULL, constant_var2=NULL, print=TRUE){
  if(length(constant_var1)>1 | length(constant_var2)>1){
    print("Error: Constant variables can only have length 1.")
  }else{
    if(!is.null(constant_cond2) && !is.null(constant_var2) && length(changing_var)==2){
      # works for models Notes.gam...
      cond_p1 = capture.output(cat(paste0("list(", changing_cond, "='", changing_var[1], "', ", constant_cond1, "='", constant_var1, "', ", constant_cond2, "='", constant_var2, "')")))
      p1=plot_smooth(x=get(model), view=values, cond = eval(parse(text=cond_p1)))
      cond_p2 = capture.output(cat(paste0("list(", changing_cond, "='", changing_var[2], "', ", constant_cond1, "='", constant_var1, "', ", constant_cond2, "='", constant_var2, "')")))
      p2=plot_smooth(x=get(model), view=values, cond = eval(parse(text=cond_p2)))
      
      # set Rho max to the max of the fit + half the difference between max of the fit and the upper limit
      max_ul = max(p1$fv$ul, p2$fv$ul)
      max_fit = max(p1$fv$fit, p2$fv$fit)
      maximum=max_fit+((max_ul-max_fit)/2)
      
      # plot in polar coordinates
      p=plot_ly(type='scatterpolar', mode='lines') %>% 
        add_trace(theta=p1$fv$theta_uncut_z*180/pi, r=p1$fv$fit, line=list(color="blue", width=2.5), name=changing_var[1]) %>% 
        add_trace(theta=p1$fv$theta_uncut_z*180/pi, r=p1$fv$ul, line=list(color="blue", dash="dot", width=0.5), showlegend=FALSE) %>% 
        add_trace(theta=p1$fv$theta_uncut_z*180/pi, r=p1$fv$ll, line=list(color="blue", dash="dot", width=0.5), showlegend=FALSE) %>% 
        add_trace(theta=p2$fv$theta_uncut_z*180/pi, r=p2$fv$fit, line=list(color="red", width=2.5), name=changing_var[2]) %>% 
        add_trace(theta=p2$fv$theta_uncut_z*180/pi, r=p2$fv$ul, line=list(color="red", dash="dot", width=0.5), showlegend=FALSE) %>% 
        add_trace(theta=p2$fv$theta_uncut_z*180/pi, r=p2$fv$ll, line=list(color="red", dash="dot", width=0.5), showlegend=FALSE) %>%
        layout(polar=list(sector=c(20,160), radialaxis=list(angle=90, range=c(0,maximum)),
                          angularaxis=list(thetaunit='radians', direction="clockwise", rotation=0)), 
               title=paste0("GAM smooths @", constant_var1, " & ", constant_var2))
      p
    }else if(is.null(constant_cond2) && is.null(constant_var2) && length(changing_var)==2){
      # no specific case yet
      cond_p1 = capture.output(cat(paste0("list(", changing_cond, "='", changing_var[1], "', ", constant_cond1, "='", constant_var1, "')")))
      p1=plot_smooth(x=get(model), view=values, cond = eval(parse(text=cond_p1)))
      cond_p2 = capture.output(cat(paste0("list(", changing_cond, "='", changing_var[2], "', ", constant_cond1, "='", constant_var1, "')")))
      p2=plot_smooth(x=get(model), view=values, cond = eval(parse(text=cond_p2)))
      
      # set Rho max to the max of the fit + half the difference between max of the fit and the upper limit
      max_ul = max(p1$fv$ul, p2$fv$ul)
      max_fit = max(p1$fv$fit, p2$fv$fit)
      maximum=max_fit+((max_ul-max_fit)/2)
      
      # plot in polar coordinates
      p=plot_ly(type='scatterpolar', mode='lines') %>% 
        add_trace(theta=p1$fv$theta_uncut_z*180/pi, r=p1$fv$fit, line=list(color="blue", width=2.5), name=changing_var[1]) %>% 
        add_trace(theta=p1$fv$theta_uncut_z*180/pi, r=p1$fv$ul, line=list(color="blue", dash="dot", width=0.5), showlegend=FALSE) %>% 
        add_trace(theta=p1$fv$theta_uncut_z*180/pi, r=p1$fv$ll, line=list(color="blue", dash="dot", width=0.5), showlegend=FALSE) %>% 
        add_trace(theta=p2$fv$theta_uncut_z*180/pi, r=p2$fv$fit, line=list(color="red", width=2.5), name=changing_var[2]) %>% 
        add_trace(theta=p2$fv$theta_uncut_z*180/pi, r=p2$fv$ul, line=list(color="red", dash="dot", width=0.5), showlegend=FALSE) %>% 
        add_trace(theta=p2$fv$theta_uncut_z*180/pi, r=p2$fv$ll, line=list(color="red", dash="dot", width=0.5), showlegend=FALSE) %>%
        layout(polar=list(sector=c(20,160), radialaxis=list(angle=90, range=c(0,maximum)),
                          angularaxis=list(thetaunit='radians', direction="clockwise", rotation=0)), 
               title=paste0("GAM smooths @", constant_var1, " & ", constant_var2))
      p
    }else if(is.null(constant_cond2) && is.null(constant_var2) && length(changing_var)>2){
      # works for models NZE.gam... or Tongan.gam...
      for (i in 1:length(changing_var)){
        if(changing_cond == constant_cond1){
          cond_p1 = capture.output(cat(paste0("list(", constant_cond1, "='", constant_var1, "')")))
          p1=plot_smooth(x=get(model), view=values, cond = eval(parse(text=cond_p1)))
          # exception for KIT (='\\\\') when not using IPA symbols
          if (changing_var[i]!="\\\\"){
            cond_p2 = capture.output(cat(paste0("list(", changing_cond, "='", changing_var[i], "')")))
            p2=plot_smooth(x=get(model), view=values, cond = eval(parse(text=cond_p2)))
          }else{
            p2=plot_smooth(x=get(model), view=values, cond = list(token.ord='\\\\'))
          }
          
          # set Rho max to the max of the fit + half the difference between max of the fit and the upper limit
          max_ul = max(p1$fv$ul, p2$fv$ul)
          max_fit = max(p1$fv$fit, p2$fv$fit)
          maximum=max_fit+((max_ul-max_fit)/2)
          # plot in polar coordinates
          p=plot_ly(type='scatterpolar', mode='lines') %>% 
            add_trace(theta=p1$fv$theta_uncut_z*180/pi, r=p1$fv$fit, line=list(color="blue", width=2.5), name=constant_var1) %>% 
            add_trace(theta=p1$fv$theta_uncut_z*180/pi, r=p1$fv$ul, line=list(color="blue", dash="dot", width=0.5), showlegend=FALSE) %>% 
            add_trace(theta=p1$fv$theta_uncut_z*180/pi, r=p1$fv$ll, line=list(color="blue", dash="dot", width=0.5), showlegend=FALSE) %>% 
            add_trace(theta=p2$fv$theta_uncut_z*180/pi, r=p2$fv$fit, line=list(color="red", width=2.5), name=changing_var[i]) %>% 
            add_trace(theta=p2$fv$theta_uncut_z*180/pi, r=p2$fv$ul, line=list(color="red", dash="dot", width=0.5), showlegend=FALSE) %>% 
            add_trace(theta=p2$fv$theta_uncut_z*180/pi, r=p2$fv$ll, line=list(color="red", dash="dot", width=0.5), showlegend=FALSE) %>%
            layout(polar=list(sector=c(20,160), radialaxis=list(angle=90, range=c(0,maximum)),
                              angularaxis=list(thetaunit='radians', direction="clockwise", rotation=0)), 
                   title=paste0("GAM smooths ",constant_var1," vs ", changing_var[i]))
          Sys.sleep(0)
          print(p)
        }
      }
    }
  }
}

1.0.2 plotly_sig_diff_notes function (Matthias Heyne, 2019) -> with updated legend position

# plot smooths with shading to indicate significant differences (Matthias Heyne, 2019)
plotly_smooths_w_sig_diff <- function(model, condition, var1, var2, values, language, print=TRUE){
  # get intervals of significant differences by running plot_diff
  # unfortunately setting plot=FALSE doesn't work as intervals of significant difference are not displayed!
  # hardcoded condition
  # output = capture.output(plot_diff(get(model), view=values, 
  #                                   comp=list(tokenPooled.ord=c(var1, var2))))
  # output = capture.output(plot_diff(get(model), view=values, comp=list(langNoteInt.ord=c(paste0("Tongan.", note, ".", intensity), paste0("NZE.", note, ".", intensity)))))
  names_smooths=list()
  if (condition=="tokenPooled.ord" && length(language)==1){
    output_comp = capture.output(cat(paste0("list(", condition, "=c(var1, var2))")))
    names_smooths[1]=var1
    names_smooths[2]=var2
    plot_title = paste0("GAM smooths ", language, " ", var1, " vs ", var2)
  }else if (condition=="langNoteInt.ord" && length(language)==2){
    output_comp = capture.output(cat(paste0("list(", condition, "=c('", language[1], ".", var1, ".", var2, 
                                            "', '", language[2], ".", var1, ".", var2, "'))")))
    names_smooths[1]=paste0(language[1], ".", var1, ".", var2)
    names_smooths[2]=paste0(language[2], ".", var1, ".", var2)
    plot_title = paste0("GAM smooths ", language[1], ".", var1, ".", var2, " vs ", language[2], ".", var1, ".", var2)
  }else if (condition=="native_lg.ord"){
    output_comp = capture.output(cat(paste0("list(", condition, "=c(var1, var2))")))
    names_smooths[1]=var1
    names_smooths[2]=var2
    plot_title = paste0("GAM smooths ", language, " ", var1, " vs ", var2)
  }
  
  # output_comp = capture.output(cat(paste0("list(", condition, "=c(var1, var2))")))
  output = capture.output(plot_diff(get(model), view=values, comp=eval(parse(text=output_comp))))
  # no significant difference
  if ((length(language)==1 && length(output)==7) | (length(language)==2 && length(output)==6)){
    cat(paste0("Smooths for ", var1, " & ", var2, " are not significantly different.\n"))
    dat1 = NA
    assign(paste0("int_sig_diff_", var1, "_", var2), dat1, envir = .GlobalEnv)
    rm(dat1)
    # run plot_smooth to grab data for polar plots
    p1 = plot_smooth(x=get(model), view=values, cond=list(tokenPooled.ord=var1, tokenPooled.ord=var2))
    p2 = plot_smooth(x=get(model), view=values, cond=list(tokenPooled.ord=var2, tokenPooled.ord=var1))
    # set Rho max to the max of the fit + half the difference between max of the fit and the upper limit
    maximum=max(p1$fv$fit, p2$fv$fit)+((max(p1$fv$ul, p2$fv$ul)-max(p1$fv$fit, p2$fv$fit))/2)
    # plot in polar coordinates
    p=plot_ly(type='scatterpolar', mode='lines') %>% 
      add_trace(theta=p1$fv$theta_uncut_z*180/pi, r=p1$fv$fit, line=list(color="blue", width=2.5), name=names_smooths[1]) %>% 
      add_trace(theta=p1$fv$theta_uncut_z*180/pi, r=p1$fv$ul, line=list(color="blue", dash="dot", width=0.5), showlegend=FALSE) %>% 
      add_trace(theta=p1$fv$theta_uncut_z*180/pi, r=p1$fv$ll, line=list(color="blue", dash="dot", width=0.5), showlegend=FALSE) %>% 
      add_trace(theta=p2$fv$theta_uncut_z*180/pi, r=p2$fv$fit, line=list(color="red", width=2.5), name=names_smooths[2]) %>% 
      add_trace(theta=p2$fv$theta_uncut_z*180/pi, r=p2$fv$ul, line=list(color="red", dash="dot", width=0.5), showlegend=FALSE) %>% 
      add_trace(theta=p2$fv$theta_uncut_z*180/pi, r=p2$fv$ll, line=list(color="red", dash="dot", width=0.5), showlegend=FALSE) %>%
      layout(polar=list(sector=c(20,160), radialaxis=list(angle=90, range=c(0,maximum)),
                        angularaxis=list(thetaunit='radians', direction="clockwise", rotation=0)), 
             title=plot_title, legend=list(orientation="h", xanchor="center", x=0.5))
    Sys.sleep(0)
    print(p)
  # there are differences...
  }else{
    # grab intervals of significant differences from output
    if (length(language)==1 && length(output)>=8){
      sig_diff1 = c(as.double(unlist(strsplit(unlist(strsplit(output[8], " "))[1], "\t"))[2]), as.double(unlist(strsplit(output[8], " "))[3]))
    }else if (length(language)==2 && length(output)>=7){
      sig_diff1 = c(as.double(unlist(strsplit(unlist(strsplit(output[7], " "))[1], "\t"))[2]), as.double(unlist(strsplit(output[7], " "))[3]))
    }
    if (length(language)==1 && length(output)>=9){
      sig_diff2 = c(as.double(unlist(strsplit(unlist(strsplit(output[9], " "))[1], "\t"))[2]), as.double(unlist(strsplit(output[9], " "))[3]))
    }else if (length(language)==2 && length(output)>=8){
      sig_diff2 = c(as.double(unlist(strsplit(unlist(strsplit(output[8], " "))[1], "\t"))[2]), as.double(unlist(strsplit(output[8], " "))[3]))
    }
    if (length(language)==1 && length(output)>=10){
      sig_diff3 = c(as.double(unlist(strsplit(unlist(strsplit(output[10], " "))[1], "\t"))[2]), as.double(unlist(strsplit(output[10], " "))[3]))
    }else if (length(language)==2 && length(output)>=9){
      sig_diff3 = c(as.double(unlist(strsplit(unlist(strsplit(output[9], " "))[1], "\t"))[2]), as.double(unlist(strsplit(output[9], " "))[3]))
    }
    if (length(language)==1 && length(output)>=11){
      sig_diff4 = c(as.double(unlist(strsplit(unlist(strsplit(output[11], " "))[1], "\t"))[2]), as.double(unlist(strsplit(output[11], " "))[3]))
    }else if (length(language)==2 && length(output)>=10){
      sig_diff4 = c(as.double(unlist(strsplit(unlist(strsplit(output[10], " "))[1], "\t"))[2]), as.double(unlist(strsplit(output[10], " "))[3]))
    }
    # write intervals of significant difference to variable
    if ((length(language)==1 && length(output)>=11) | (length(language)==2 && length(output)>=10)){
      dat1 = c(sig_diff1, sig_diff2, sig_diff3, sig_diff4)
    }else if ((length(language)==1 && length(output)>=10) | (length(language)==2 && length(output)>=9)){
      dat1 = c(sig_diff1, sig_diff2, sig_diff3)
    }else if ((length(language)==1 && length(output)>=9) | (length(language)==2 && length(output)>=8)){
      dat1 = c(sig_diff1, sig_diff2)
    }else{
      dat1 = sig_diff1
    }
    assign(paste0("int_sig_diff_", var1, "_", var2), dat1, envir = .GlobalEnv)
    rm(dat1, output)
    # run plot_smooth to grab data for polar plots
    if (condition=="tokenPooled.ord" && length(language)==1){
      cond_p1 = capture.output(cat(paste0("list(", condition, "=var1)")))
      cond_p2 = capture.output(cat(paste0("list(", condition, "=var2)")))
    }else if (condition=="langNoteInt.ord" && length(language)==2){
      cond_p1 = capture.output(cat(paste0("list(", condition, "='", language[1], ".", var1, ".", var2, 
                                "', ", condition, "='", language[2], ".", var1, ".", var2, "')")))
      cond_p2 = capture.output(cat(paste0("list(", condition, "='", language[2], ".", var1, ".", var2, 
                                          "', ", condition, "='", language[1], ".", var1, ".", var2, "')")))
    }else if (condition=="native_lg.ord"){
      cond_p1 = capture.output(cat(paste0("list(", condition, "=var1)")))
      cond_p2 = capture.output(cat(paste0("list(", condition, "=var2)")))
    }
    # hardcoded condition
    p1 = plot_smooth(x=get(model), view=values, cond=eval(parse(text=cond_p1)))
    p2 = plot_smooth(x=get(model), view=values, cond=eval(parse(text=cond_p2)))
    # set Rho max to the max of the fit + half the difference between max of the fit and the upper limit
    maximum=max(p1$fv$fit, p2$fv$fit)+((max(p1$fv$ul, p2$fv$ul)-max(p1$fv$fit, p2$fv$fit))/2)
    # plot in polar coordinates
    if (exists("sig_diff4")){
      p=plot_ly(type='scatterpolar', mode='lines') %>% 
        add_trace(theta=p1$fv$theta_uncut_z*180/pi, r=p1$fv$fit, line=list(color="blue", width=2.5), name=names_smooths[1]) %>% 
        add_trace(theta=p1$fv$theta_uncut_z*180/pi, r=p1$fv$ul, line=list(color="blue", dash="dot", width=0.5), showlegend=FALSE) %>% 
        add_trace(theta=p1$fv$theta_uncut_z*180/pi, r=p1$fv$ll, line=list(color="blue", dash="dot", width=0.5), showlegend=FALSE) %>% 
        add_trace(theta=p2$fv$theta_uncut_z*180/pi, r=p2$fv$fit, line=list(color="red", width=2.5), name=names_smooths[2]) %>% 
        add_trace(theta=p2$fv$theta_uncut_z*180/pi, r=p2$fv$ul, line=list(color="red", dash="dot", width=0.5), showlegend=FALSE) %>% 
        add_trace(theta=p2$fv$theta_uncut_z*180/pi, r=p2$fv$ll, line=list(color="red", dash="dot", width=0.5), showlegend=FALSE) %>%
        add_trace(theta=seq(sig_diff1[1]*180/pi, sig_diff1[2]*180/pi, length.out=20), 
                  r=c(0, rep(maximum, 18), 0), line=list(color="black", width=0.5), fill="toself", fillcolor=rgb(0,0,0,max=255,alpha=25), showlegend=FALSE) %>%
        add_trace(theta=seq(sig_diff2[1]*180/pi, sig_diff2[2]*180/pi, length.out=20), 
                  r=c(0, rep(maximum, 18), 0), line=list(color="black", width=0.5), fill="toself", fillcolor=rgb(0,0,0,max=255,alpha=25), showlegend=FALSE) %>%
        add_trace(theta=seq(sig_diff3[1]*180/pi, sig_diff3[2]*180/pi, length.out=20), 
                  r=c(0, rep(maximum, 18), 0), line=list(color="black", width=0.5), fill="toself", fillcolor=rgb(0,0,0,max=255,alpha=25), showlegend=FALSE) %>%
        add_trace(theta=seq(sig_diff4[1]*180/pi, sig_diff4[2]*180/pi, length.out=20), 
                  r=c(0, rep(maximum, 18), 0), line=list(color="black", width=0.5), fill="toself", fillcolor=rgb(0,0,0,max=255,alpha=25), showlegend=FALSE) %>%
        layout(polar=list(sector=c(20,160), radialaxis=list(angle=90, range=c(0,maximum)),
                          angularaxis=list(thetaunit='radians', direction="clockwise", rotation=0)), 
               title=plot_title, legend=list(orientation="h", xanchor="center", x=0.5))
      Sys.sleep(0)
      print(p)
    }else if (exists("sig_diff3")){
      p=plot_ly(type='scatterpolar', mode='lines') %>% 
        add_trace(theta=p1$fv$theta_uncut_z*180/pi, r=p1$fv$fit, line=list(color="blue", width=2.5), name=names_smooths[1]) %>% 
        add_trace(theta=p1$fv$theta_uncut_z*180/pi, r=p1$fv$ul, line=list(color="blue", dash="dot", width=0.5), showlegend=FALSE) %>% 
        add_trace(theta=p1$fv$theta_uncut_z*180/pi, r=p1$fv$ll, line=list(color="blue", dash="dot", width=0.5), showlegend=FALSE) %>% 
        add_trace(theta=p2$fv$theta_uncut_z*180/pi, r=p2$fv$fit, line=list(color="red", width=2.5), name=names_smooths[2]) %>% 
        add_trace(theta=p2$fv$theta_uncut_z*180/pi, r=p2$fv$ul, line=list(color="red", dash="dot", width=0.5), showlegend=FALSE) %>% 
        add_trace(theta=p2$fv$theta_uncut_z*180/pi, r=p2$fv$ll, line=list(color="red", dash="dot", width=0.5), showlegend=FALSE) %>%
        add_trace(theta=seq(sig_diff1[1]*180/pi, sig_diff1[2]*180/pi, length.out=20), 
                  r=c(0, rep(maximum, 18), 0), line=list(color="black", width=0.5), fill="toself", fillcolor=rgb(0,0,0,max=255,alpha=25), showlegend=FALSE) %>%
        add_trace(theta=seq(sig_diff2[1]*180/pi, sig_diff2[2]*180/pi, length.out=20), 
                  r=c(0, rep(maximum, 18), 0), line=list(color="black", width=0.5), fill="toself", fillcolor=rgb(0,0,0,max=255,alpha=25), showlegend=FALSE) %>%
        add_trace(theta=seq(sig_diff3[1]*180/pi, sig_diff3[2]*180/pi, length.out=20), 
                  r=c(0, rep(maximum, 18), 0), line=list(color="black", width=0.5), fill="toself", fillcolor=rgb(0,0,0,max=255,alpha=25), showlegend=FALSE) %>%
        layout(polar=list(sector=c(20,160), radialaxis=list(angle=90, range=c(0,maximum)),
                          angularaxis=list(thetaunit='radians', direction="clockwise", rotation=0)), 
               title=plot_title, legend=list(orientation="h", xanchor="center", x=0.5))
      Sys.sleep(0)
      print(p)
    }else if (exists("sig_diff2")){
      p=plot_ly(type='scatterpolar', mode='lines') %>% 
        add_trace(theta=p1$fv$theta_uncut_z*180/pi, r=p1$fv$fit, line=list(color="blue", width=2.5), name=names_smooths[1]) %>% 
        add_trace(theta=p1$fv$theta_uncut_z*180/pi, r=p1$fv$ul, line=list(color="blue", dash="dot", width=0.5), showlegend=FALSE) %>% 
        add_trace(theta=p1$fv$theta_uncut_z*180/pi, r=p1$fv$ll, line=list(color="blue", dash="dot", width=0.5), showlegend=FALSE) %>% 
        add_trace(theta=p2$fv$theta_uncut_z*180/pi, r=p2$fv$fit, line=list(color="red", width=2.5), name=names_smooths[2]) %>% 
        add_trace(theta=p2$fv$theta_uncut_z*180/pi, r=p2$fv$ul, line=list(color="red", dash="dot", width=0.5), showlegend=FALSE) %>% 
        add_trace(theta=p2$fv$theta_uncut_z*180/pi, r=p2$fv$ll, line=list(color="red", dash="dot", width=0.5), showlegend=FALSE) %>%
        add_trace(theta=seq(sig_diff1[1]*180/pi, sig_diff1[2]*180/pi, length.out=20), 
                  r=c(0, rep(maximum, 18), 0), line=list(color="black", width=0.5), fill="toself", fillcolor=rgb(0,0,0,max=255,alpha=25), showlegend=FALSE) %>%
        add_trace(theta=seq(sig_diff2[1]*180/pi, sig_diff2[2]*180/pi, length.out=20), 
                  r=c(0, rep(maximum, 18), 0), line=list(color="black", width=0.5), fill="toself", fillcolor=rgb(0,0,0,max=255,alpha=25), showlegend=FALSE) %>%
        layout(polar=list(sector=c(20,160), radialaxis=list(angle=90, range=c(0,maximum)),
                          angularaxis=list(thetaunit='radians', direction="clockwise", rotation=0)), 
               title=plot_title, legend=list(orientation="h", xanchor="center", x=0.5))
      Sys.sleep(0)
      print(p)
    }else{
      p=plot_ly(type='scatterpolar', mode='lines') %>% 
        add_trace(theta=p1$fv$theta_uncut_z*180/pi, r=p1$fv$fit, line=list(color="blue", width=2.5), name=names_smooths[1]) %>% 
        add_trace(theta=p1$fv$theta_uncut_z*180/pi, r=p1$fv$ul, line=list(color="blue", dash="dot", width=0.5), showlegend=FALSE) %>% 
        add_trace(theta=p1$fv$theta_uncut_z*180/pi, r=p1$fv$ll, line=list(color="blue", dash="dot", width=0.5), showlegend=FALSE) %>% 
        add_trace(theta=p2$fv$theta_uncut_z*180/pi, r=p2$fv$fit, line=list(color="red", width=2.5), name=names_smooths[2]) %>% 
        add_trace(theta=p2$fv$theta_uncut_z*180/pi, r=p2$fv$ul, line=list(color="red", dash="dot", width=0.5), showlegend=FALSE) %>% 
        add_trace(theta=p2$fv$theta_uncut_z*180/pi, r=p2$fv$ll, line=list(color="red", dash="dot", width=0.5), showlegend=FALSE) %>%
        add_trace(theta=seq(sig_diff1[1]*180/pi, sig_diff1[2]*180/pi, length.out=20), 
                  r=c(0, rep(maximum, 18), 0), line=list(color="black", width=0.5), fill="toself", fillcolor=rgb(0,0,0,max=255,alpha=25), showlegend=FALSE) %>%
        layout(polar=list(sector=c(20,160), radialaxis=list(angle=90, range=c(0,maximum)),
                          angularaxis=list(thetaunit='radians', direction="clockwise", rotation=0)), 
               title=plot_title, legend=list(orientation="h", xanchor="center", x=0.5))
      Sys.sleep(0)
      print(p)
    }
  }
}

2 load in data

df <- read.csv("all_data_NZE_Tongan_w_context_checked_7_March_2019_not_cut_checked_27_Apr.csv", sep=',', stringsAsFactors = F)
# remove empty column
df$X = NULL
df$tokenPooled <- factor(df$tokenPooled)
df$subject <- factor(df$subject)
df$sex <- factor(df$sex)
df$native_lg <- factor(df$native_lg)
# updated 
df$playing_proficiency[df$playing_proficiency == "intermediate"] <- "amateur"
df$playing_proficiency <- factor(df$playing_proficiency, levels = c("amateur","semi-professional","professional"))
df$block <- factor(df$block)
df$theta_uncut_z <- as.numeric(df$theta_uncut_z)
# updated
df$note_intensity <- factor(df$note_intensity, levels = c("piano","mezzopiano","mezzoforte","forte"))
df$tokenPooled <- factor(df$tokenPooled)

3 predict average values for note productions NZE vs Tongan

3.1 Data manipulation

dfSummary <- group_by(df, subject, playing_proficiency, activity, native_lg, tokenPooled, theta_uncut_z_group = cut(theta_uncut_z,breaks=100)) %>% summarise(rhoVar = sd(rho_uncut_z,na.rm=TRUE))
dfSummary$theta_uncut_z = as.character(dfSummary$theta_uncut_z_group)
dfSummary$theta_uncut_z = gsub("\\[|\\]|\\(|\\)", "",dfSummary$theta_uncut_z)
dfSummary$theta_uncut_z = strsplit(dfSummary$theta_uncut_z,",")
dfSummary$theta_uncut_z2 = 1
for(i in c(1:nrow(dfSummary)))
{
  dfSummary$theta_uncut_z2[i] = mean(as.numeric(unlist(dfSummary$theta_uncut_z[i])))
}
dfSummary$theta_uncut_z=dfSummary$theta_uncut_z2
dfSummary$playing_proficiency.ord <- as.ordered(dfSummary$playing_proficiency)
contrasts(dfSummary$playing_proficiency.ord) <- "contr.treatment"
dfSummary$activity.ord <- as.ordered(dfSummary$activity)
contrasts(dfSummary$activity.ord) <- "contr.treatment"
dfSummary$langNoteInt <- interaction(dfSummary$native_lg, 
dfSummary$tokenPooled)
dfSummary$langNoteInt.ord <- as.ordered(dfSummary$langNoteInt)
contrasts(dfSummary$langNoteInt.ord) <- "contr.treatment"
dfSummary$native_lg.ord <- as.ordered(dfSummary$native_lg)
contrasts(dfSummary$native_lg.ord) <- "contr.treatment"
dfSummary$tokenPooled.ord <- as.ordered(dfSummary$tokenPooled)
contrasts(dfSummary$tokenPooled.ord) <- "contr.treatment"
dfSummary = na.omit(dfSummary)
for(i in unique(dfSummary$subject))
{
  dfSubject = subset(dfSummary,dfSummary$subject == i)
  for(j in unique(dfSubject$tokenPooled))
  {
    dfSummary$start[dfSummary$subject == i & dfSummary$tokenPooled == j] <- 
      dfSummary$theta_uncut_z[dfSummary$subject == i & dfSummary$tokenPooled == j] ==
      min(dfSummary$theta_uncut_z[dfSummary$subject == i & dfSummary$tokenPooled == j])
  }
}

3.2 Model specification

if (run_models == TRUE){
  mdl.sys.time1 <- system.time(VAR.gam.noAR.Mod1 <- bam(rhoVar ~ langNoteInt.ord + s(theta_uncut_z, bs="cr", k=10) + s(theta_uncut_z, bs="cr", k=10, by=langNoteInt.ord) +s(theta_uncut_z, subject, bs="fs", k=10, m=1, by=langNoteInt.ord), data=dfSummary, discrete=TRUE, nthreads=ncores, method = "fREML"))
   mdl.sys.time1
   # save model & model summary so they can be reloaded later
   saveRDS(VAR.gam.noAR.Mod1, paste0(output_dir,"/VAR.gam.noAR.Mod1.rds"))
   capture.output(summary(VAR.gam.noAR.Mod1), 
                  file = paste0(output_dir,"/summary_VAR.gam.noAR.Mod1.txt"))
}else{
  # reload model from output_dir
  VAR.gam.noAR.Mod1 = readRDS(paste0(output_dir,"/VAR.gam.noAR.Mod1.rds"))
}
if (run_models == TRUE){
  # set start_value_rho from VAR.gam.noAR.Mod1 as rho_est for the next model
  rho_est <- start_value_rho(VAR.gam.noAR.Mod1)
  mdl.sys.time2 <- system.time(VAR.gam.AR.Mod2 <- bam(rhoVar ~ langNoteInt.ord + s(theta_uncut_z, bs="cr", k=10) + s(theta_uncut_z, bs="cr", k=10, by=langNoteInt.ord) +  s(theta_uncut_z, subject, bs="fs", k=10, m=1, by=langNoteInt.ord), AR.start=dfSummary$start, rho=rho_est, data=dfSummary, discrete=TRUE, nthreads=ncores, method = "fREML"))
  mdl.sys.time2
  # save model & model summary so they can be reloaded later
  saveRDS(VAR.gam.AR.Mod2, paste0(output_dir,"/VAR.gam.AR.Mod2.rds"))
  capture.output(summary(VAR.gam.AR.Mod2), 
                 file = paste0(output_dir,"/summary_VAR.gam.AR.Mod2.txt"))
}else{
  # reload model from output_dir
  VAR.gam.AR.Mod2 = readRDS(paste0(output_dir,"/VAR.gam.AR.Mod2.rds"))
}

3.3 Model inspection

3.3.1 Checking ACF

3.3.1.1 Full

acf_resid(VAR.gam.AR.Mod2, main = "Average ACF AR", cex.lab=1.5, cex.axis=1.5)

3.3.1.2 By Token

acf_resid(VAR.gam.AR.Mod2,split_pred=list(dfSummary$tokenPooled),main = "Average ACF AR by tokenPooled",cex.lab=1.5,cex.axis=1.5)

3.3.1.3 By Language

acf_resid(VAR.gam.AR.Mod2,split_pred=list(dfSummary$native_lg),main = "Average ACF AR by native language",cex.lab=1.5,cex.axis=1.5)

3.3.2 Summary of the model

summary(VAR.gam.AR.Mod2)

Family: gaussian 
Link function: identity 

Formula:
rhoVar ~ langNoteInt.ord + s(theta_uncut_z, bs = "cr", 
    k = 10) + s(theta_uncut_z, bs = "cr", k = 10, by = langNoteInt.ord) + 
    s(theta_uncut_z, subject, bs = "fs", k = 10, m = 1, 
        by = langNoteInt.ord)

Parametric coefficients:
                           Estimate Std. Error t value Pr(>|t|)    
(Intercept)                 8.00231    0.10777  74.256  < 2e-16 ***
langNoteInt.ordNZE.É\u0090      -0.97363    1.61302  -0.604 0.546111    
langNoteInt.ordNZE.É\u0090Ë\u0090    -2.64035    1.85143  -1.426 0.153854    
langNoteInt.ordNZE.É’      -2.46702    2.76454  -0.892 0.372202    
langNoteInt.ordNZE.Bb2     -1.98406    1.29226  -1.535 0.124720    
langNoteInt.ordTongan.Bb2  -1.41836    1.41220  -1.004 0.315220    
langNoteInt.ordNZE.Bb3     -2.98062    1.73953  -1.713 0.086644 .  
langNoteInt.ordTongan.Bb3  -3.58208    2.20014  -1.628 0.103519    
langNoteInt.ordNZE.D4      -4.14783    1.66244  -2.495 0.012604 *  
langNoteInt.ordTongan.D4   -5.16170    1.97641  -2.612 0.009018 ** 
langNoteInt.ordNZE.e        0.50229    1.63619   0.307 0.758855    
langNoteInt.ordTongan.e    -2.15181    0.92909  -2.316 0.020568 *  
langNoteInt.ordNZE.É™      -0.07156    1.26678  -0.056 0.954950    
langNoteInt.ordNZE.É™#     -1.81077    0.40448  -4.477 7.63e-06 ***
langNoteInt.ordNZE.É›      -1.25424    1.83884  -0.682 0.495196    
langNoteInt.ordNZE.ɘ       0.04167    2.05228   0.020 0.983800    
langNoteInt.ordNZE.F3      -3.09511    1.73763  -1.781 0.074894 .  
langNoteInt.ordTongan.F3   -2.53651    1.38509  -1.831 0.067074 .  
langNoteInt.ordNZE.F4      -5.29805    1.44440  -3.668 0.000245 ***
langNoteInt.ordTongan.F4   -8.89295    2.81838  -3.155 0.001606 ** 
langNoteInt.ordTongan.i    -1.95829    1.33837  -1.463 0.143434    
langNoteInt.ordNZE.iË\u0090    -29.28668   16.83868  -1.739 0.082009 .  
langNoteInt.ordTongan.o    -0.92331    5.02574  -0.184 0.854239    
langNoteInt.ordNZE.oË\u0090     -2.13673    1.64411  -1.300 0.193747    
langNoteInt.ordNZE.ɵË\u0090    -1.62651    2.37389  -0.685 0.493247    
langNoteInt.ordTongan.u    -6.83503   10.71965  -0.638 0.523732    
langNoteInt.ordNZE.ʉË\u0090    -3.21586    3.80494  -0.845 0.398022    
langNoteInt.ordNZE.ÊŠ      -1.02949    3.74579  -0.275 0.783444    
---
Signif. codes:  0 ‘***’ 0.001 ‘**’ 0.01 ‘*’ 0.05 ‘.’ 0.1 ‘ ’ 1

Approximate significance of smooth terms:
                                                      edf  Ref.df
s(theta_uncut_z)                                    8.872   8.936
s(theta_uncut_z):langNoteInt.ordNZE.É\u0090              5.546   5.946
s(theta_uncut_z):langNoteInt.ordNZE.É\u0090Ë\u0090            5.237   5.619
s(theta_uncut_z):langNoteInt.ordNZE.É’              4.973   5.297
s(theta_uncut_z):langNoteInt.ordNZE.Bb2             4.453   4.756
s(theta_uncut_z):langNoteInt.ordTongan.Bb2          5.678   6.024
s(theta_uncut_z):langNoteInt.ordNZE.Bb3             1.003   1.004
s(theta_uncut_z):langNoteInt.ordTongan.Bb3          7.791   8.078
s(theta_uncut_z):langNoteInt.ordNZE.D4              2.924   3.092
s(theta_uncut_z):langNoteInt.ordTongan.D4           3.844   4.110
s(theta_uncut_z):langNoteInt.ordNZE.e               6.911   7.197
s(theta_uncut_z):langNoteInt.ordTongan.e            6.022   6.443
s(theta_uncut_z):langNoteInt.ordNZE.É™              8.038   8.378
s(theta_uncut_z):langNoteInt.ordNZE.É™#             8.412   8.698
s(theta_uncut_z):langNoteInt.ordNZE.É›              6.415   6.796
s(theta_uncut_z):langNoteInt.ordNZE.ɘ              7.059   7.409
s(theta_uncut_z):langNoteInt.ordNZE.F3              1.001   1.001
s(theta_uncut_z):langNoteInt.ordTongan.F3           6.412   6.792
s(theta_uncut_z):langNoteInt.ordNZE.F4              4.088   4.346
s(theta_uncut_z):langNoteInt.ordTongan.F4           4.886   5.195
s(theta_uncut_z):langNoteInt.ordTongan.i            7.799   8.150
s(theta_uncut_z):langNoteInt.ordNZE.iË\u0090             6.118   6.552
s(theta_uncut_z):langNoteInt.ordTongan.o            6.065   6.458
s(theta_uncut_z):langNoteInt.ordNZE.oË\u0090             5.824   6.194
s(theta_uncut_z):langNoteInt.ordNZE.ɵË\u0090            1.001   1.001
s(theta_uncut_z):langNoteInt.ordTongan.u            6.249   6.720
s(theta_uncut_z):langNoteInt.ordNZE.ʉË\u0090            1.001   1.001
s(theta_uncut_z):langNoteInt.ordNZE.ÊŠ              2.316   2.436
s(theta_uncut_z,subject):langNoteInt.ordNZE.É\u0090     70.857 100.000
s(theta_uncut_z,subject):langNoteInt.ordNZE.É\u0090Ë\u0090   70.884 100.000
s(theta_uncut_z,subject):langNoteInt.ordNZE.É’     79.953 100.000
s(theta_uncut_z,subject):langNoteInt.ordNZE.Bb2    66.321  99.000
s(theta_uncut_z,subject):langNoteInt.ordTongan.Bb2 66.393  99.000
s(theta_uncut_z,subject):langNoteInt.ordNZE.Bb3    71.568  99.000
s(theta_uncut_z,subject):langNoteInt.ordTongan.Bb3 69.313  99.000
s(theta_uncut_z,subject):langNoteInt.ordNZE.D4     67.242  99.000
s(theta_uncut_z,subject):langNoteInt.ordTongan.D4  68.879  99.000
s(theta_uncut_z,subject):langNoteInt.ordNZE.e      66.160  99.000
s(theta_uncut_z,subject):langNoteInt.ordTongan.e   61.414  99.000
s(theta_uncut_z,subject):langNoteInt.ordNZE.É™     59.777  99.000
s(theta_uncut_z,subject):langNoteInt.ordNZE.É™#    48.910  99.000
s(theta_uncut_z,subject):langNoteInt.ordNZE.É›     69.393  99.000
s(theta_uncut_z,subject):langNoteInt.ordNZE.ɘ     71.632  99.000
s(theta_uncut_z,subject):langNoteInt.ordNZE.F3     75.905  99.000
s(theta_uncut_z,subject):langNoteInt.ordTongan.F3  66.936  99.000
s(theta_uncut_z,subject):langNoteInt.ordNZE.F4     61.214  99.000
s(theta_uncut_z,subject):langNoteInt.ordTongan.F4  66.915  99.000
s(theta_uncut_z,subject):langNoteInt.ordTongan.i   62.482  99.000
s(theta_uncut_z,subject):langNoteInt.ordNZE.iË\u0090    79.667  99.000
s(theta_uncut_z,subject):langNoteInt.ordTongan.o   82.606 100.000
s(theta_uncut_z,subject):langNoteInt.ordNZE.oË\u0090    68.673  99.000
s(theta_uncut_z,subject):langNoteInt.ordNZE.ɵË\u0090   77.097  99.000
s(theta_uncut_z,subject):langNoteInt.ordTongan.u   84.433  99.000
s(theta_uncut_z,subject):langNoteInt.ordNZE.ʉË\u0090   81.023  99.000
s(theta_uncut_z,subject):langNoteInt.ordNZE.ÊŠ     77.375  99.000
                                                        F  p-value
s(theta_uncut_z)                                   70.489  < 2e-16
s(theta_uncut_z):langNoteInt.ordNZE.É\u0090              1.445 0.169930
s(theta_uncut_z):langNoteInt.ordNZE.É\u0090Ë\u0090            2.493 0.025088
s(theta_uncut_z):langNoteInt.ordNZE.É’              1.250 0.205920
s(theta_uncut_z):langNoteInt.ordNZE.Bb2             1.584 0.301922
s(theta_uncut_z):langNoteInt.ordTongan.Bb2          2.210 0.041133
s(theta_uncut_z):langNoteInt.ordNZE.Bb3             0.093 0.762294
s(theta_uncut_z):langNoteInt.ordTongan.Bb3          3.113 0.000804
s(theta_uncut_z):langNoteInt.ordNZE.D4              1.113 0.345495
s(theta_uncut_z):langNoteInt.ordTongan.D4           1.625 0.157326
s(theta_uncut_z):langNoteInt.ordNZE.e               3.014 0.004660
s(theta_uncut_z):langNoteInt.ordTongan.e            1.728 0.073853
s(theta_uncut_z):langNoteInt.ordNZE.É™              8.910 1.75e-11
s(theta_uncut_z):langNoteInt.ordNZE.É™#            18.668  < 2e-16
s(theta_uncut_z):langNoteInt.ordNZE.É›              2.142 0.067326
s(theta_uncut_z):langNoteInt.ordNZE.ɘ              3.775 0.000484
s(theta_uncut_z):langNoteInt.ordNZE.F3              0.057 0.812421
s(theta_uncut_z):langNoteInt.ordTongan.F3           2.265 0.018740
s(theta_uncut_z):langNoteInt.ordNZE.F4              1.708 0.170357
s(theta_uncut_z):langNoteInt.ordTongan.F4           2.669 0.033058
s(theta_uncut_z):langNoteInt.ordTongan.i            3.002 0.001150
s(theta_uncut_z):langNoteInt.ordNZE.iË\u0090             2.756 0.006887
s(theta_uncut_z):langNoteInt.ordTongan.o            2.203 0.048544
s(theta_uncut_z):langNoteInt.ordNZE.oË\u0090             2.666 0.012507
s(theta_uncut_z):langNoteInt.ordNZE.ɵË\u0090            0.026 0.873668
s(theta_uncut_z):langNoteInt.ordTongan.u            2.042 0.055998
s(theta_uncut_z):langNoteInt.ordNZE.ʉË\u0090            0.413 0.520613
s(theta_uncut_z):langNoteInt.ordNZE.ÊŠ              0.180 0.783067
s(theta_uncut_z,subject):langNoteInt.ordNZE.É\u0090      6.865  < 2e-16
s(theta_uncut_z,subject):langNoteInt.ordNZE.É\u0090Ë\u0090    7.818  < 2e-16
s(theta_uncut_z,subject):langNoteInt.ordNZE.É’     18.664  < 2e-16
s(theta_uncut_z,subject):langNoteInt.ordNZE.Bb2    10.303  < 2e-16
s(theta_uncut_z,subject):langNoteInt.ordTongan.Bb2 18.281  < 2e-16
s(theta_uncut_z,subject):langNoteInt.ordNZE.Bb3    14.466  < 2e-16
s(theta_uncut_z,subject):langNoteInt.ordTongan.Bb3 22.632  < 2e-16
s(theta_uncut_z,subject):langNoteInt.ordNZE.D4     13.933  < 2e-16
s(theta_uncut_z,subject):langNoteInt.ordTongan.D4  25.480  < 2e-16
s(theta_uncut_z,subject):langNoteInt.ordNZE.e      12.291  < 2e-16
s(theta_uncut_z,subject):langNoteInt.ordTongan.e    8.573  < 2e-16
s(theta_uncut_z,subject):langNoteInt.ordNZE.É™     14.365  < 2e-16
s(theta_uncut_z,subject):langNoteInt.ordNZE.É™#     3.117  < 2e-16
s(theta_uncut_z,subject):langNoteInt.ordNZE.É›      8.070  < 2e-16
s(theta_uncut_z,subject):langNoteInt.ordNZE.ɘ     13.504  < 2e-16
s(theta_uncut_z,subject):langNoteInt.ordNZE.F3     15.014  < 2e-16
s(theta_uncut_z,subject):langNoteInt.ordTongan.F3  20.935  < 2e-16
s(theta_uncut_z,subject):langNoteInt.ordNZE.F4     11.949  < 2e-16
s(theta_uncut_z,subject):langNoteInt.ordTongan.F4  26.468  < 2e-16
s(theta_uncut_z,subject):langNoteInt.ordTongan.i   14.004  < 2e-16
s(theta_uncut_z,subject):langNoteInt.ordNZE.iË\u0090    45.669  < 2e-16
s(theta_uncut_z,subject):langNoteInt.ordTongan.o   22.896  < 2e-16
s(theta_uncut_z,subject):langNoteInt.ordNZE.oË\u0090    13.644  < 2e-16
s(theta_uncut_z,subject):langNoteInt.ordNZE.ɵË\u0090   12.675  < 2e-16
s(theta_uncut_z,subject):langNoteInt.ordTongan.u   43.466  < 2e-16
s(theta_uncut_z,subject):langNoteInt.ordNZE.ʉË\u0090   22.778  < 2e-16
s(theta_uncut_z,subject):langNoteInt.ordNZE.ÊŠ     28.619  < 2e-16
                                                      
s(theta_uncut_z)                                   ***
s(theta_uncut_z):langNoteInt.ordNZE.É\u0090                
s(theta_uncut_z):langNoteInt.ordNZE.É\u0090Ë\u0090           *  
s(theta_uncut_z):langNoteInt.ordNZE.É’                
s(theta_uncut_z):langNoteInt.ordNZE.Bb2               
s(theta_uncut_z):langNoteInt.ordTongan.Bb2         *  
s(theta_uncut_z):langNoteInt.ordNZE.Bb3               
s(theta_uncut_z):langNoteInt.ordTongan.Bb3         ***
s(theta_uncut_z):langNoteInt.ordNZE.D4                
s(theta_uncut_z):langNoteInt.ordTongan.D4             
s(theta_uncut_z):langNoteInt.ordNZE.e              ** 
s(theta_uncut_z):langNoteInt.ordTongan.e           .  
s(theta_uncut_z):langNoteInt.ordNZE.É™             ***
s(theta_uncut_z):langNoteInt.ordNZE.É™#            ***
s(theta_uncut_z):langNoteInt.ordNZE.É›             .  
s(theta_uncut_z):langNoteInt.ordNZE.ɘ             ***
s(theta_uncut_z):langNoteInt.ordNZE.F3                
s(theta_uncut_z):langNoteInt.ordTongan.F3          *  
s(theta_uncut_z):langNoteInt.ordNZE.F4                
s(theta_uncut_z):langNoteInt.ordTongan.F4          *  
s(theta_uncut_z):langNoteInt.ordTongan.i           ** 
s(theta_uncut_z):langNoteInt.ordNZE.iË\u0090            ** 
s(theta_uncut_z):langNoteInt.ordTongan.o           *  
s(theta_uncut_z):langNoteInt.ordNZE.oË\u0090            *  
s(theta_uncut_z):langNoteInt.ordNZE.ɵË\u0090              
s(theta_uncut_z):langNoteInt.ordTongan.u           .  
s(theta_uncut_z):langNoteInt.ordNZE.ʉË\u0090              
s(theta_uncut_z):langNoteInt.ordNZE.ÊŠ                
s(theta_uncut_z,subject):langNoteInt.ordNZE.É\u0090     ***
s(theta_uncut_z,subject):langNoteInt.ordNZE.É\u0090Ë\u0090   ***
s(theta_uncut_z,subject):langNoteInt.ordNZE.É’     ***
s(theta_uncut_z,subject):langNoteInt.ordNZE.Bb2    ***
s(theta_uncut_z,subject):langNoteInt.ordTongan.Bb2 ***
s(theta_uncut_z,subject):langNoteInt.ordNZE.Bb3    ***
s(theta_uncut_z,subject):langNoteInt.ordTongan.Bb3 ***
s(theta_uncut_z,subject):langNoteInt.ordNZE.D4     ***
s(theta_uncut_z,subject):langNoteInt.ordTongan.D4  ***
s(theta_uncut_z,subject):langNoteInt.ordNZE.e      ***
s(theta_uncut_z,subject):langNoteInt.ordTongan.e   ***
s(theta_uncut_z,subject):langNoteInt.ordNZE.É™     ***
s(theta_uncut_z,subject):langNoteInt.ordNZE.É™#    ***
s(theta_uncut_z,subject):langNoteInt.ordNZE.É›     ***
s(theta_uncut_z,subject):langNoteInt.ordNZE.ɘ     ***
s(theta_uncut_z,subject):langNoteInt.ordNZE.F3     ***
s(theta_uncut_z,subject):langNoteInt.ordTongan.F3  ***
s(theta_uncut_z,subject):langNoteInt.ordNZE.F4     ***
s(theta_uncut_z,subject):langNoteInt.ordTongan.F4  ***
s(theta_uncut_z,subject):langNoteInt.ordTongan.i   ***
s(theta_uncut_z,subject):langNoteInt.ordNZE.iË\u0090    ***
s(theta_uncut_z,subject):langNoteInt.ordTongan.o   ***
s(theta_uncut_z,subject):langNoteInt.ordNZE.oË\u0090    ***
s(theta_uncut_z,subject):langNoteInt.ordNZE.ɵË\u0090   ***
s(theta_uncut_z,subject):langNoteInt.ordTongan.u   ***
s(theta_uncut_z,subject):langNoteInt.ordNZE.ʉË\u0090   ***
s(theta_uncut_z,subject):langNoteInt.ordNZE.ÊŠ     ***
---
Signif. codes:  0 ‘***’ 0.001 ‘**’ 0.01 ‘*’ 0.05 ‘.’ 0.1 ‘ ’ 1

R-sq.(adj) =  0.868   Deviance explained = 88.2%
fREML =  36912  Scale est. = 2.0136    n = 19150

3.3.3 Plotting model predictions

3.3.3.1 Overall variance differences

And finally overall variance differences by language

# make copy of dfNotes
dat1 = dfSummary
dat1$predicted_values = predict(VAR.gam.AR.Mod2)
# plot in polar coordinates using plotly
dat1_NZE = dat1[dat1$native_lg == "NZE",]
dat1_Tongan = dat1[dat1$native_lg == "Tongan",]
# estimate smooths using R's generic predict.smooth.spline function
smooth_NZE=list(theta=seq(min(dat1_NZE$theta_uncut_z)*180/pi, max(dat1_NZE$theta_uncut_z)*180/pi, length=100), r=predict(smooth.spline(dat1_NZE$theta_uncut_z, dat1_NZE$predicted_values),
 seq(min(dat1_NZE$theta_uncut_z), max(dat1_NZE$theta_uncut_z), length=100))$y, line=list(color="blue", dash="dash"))
smooth_Tongan=list(theta=seq(min(dat1_Tongan$theta_uncut_z)*180/pi, max(dat1_Tongan$theta_uncut_z)*180/pi, length=100), r=predict(smooth.spline(dat1_Tongan$theta_uncut_z, dat1_Tongan$predicted_values),
 seq(min(dat1_Tongan$theta_uncut_z), max(dat1_Tongan$theta_uncut_z), length=100))$y, line=list(color="red", dash=""))
# set Rho max to the max of the predicted_values + 5
max_predictions = max(max(smooth_NZE$r), max(smooth_Tongan$r))
maximum=max_predictions+5
rm(max_predictions)
p = plot_ly(type='scatterpolar', mode='lines') %>%
add_trace(theta=smooth_NZE$theta, r=smooth_NZE$r, line=list(color=smooth_NZE$line$color[[1]], width=2.5, dash=smooth_NZE$line$dash[[1]]), name="overall average of NZE notes") %>%
  add_trace(theta=smooth_Tongan$theta, r=smooth_Tongan$r, line=list(color=smooth_Tongan$line$color[[1]], width=2.5, dash=smooth_Tongan$line$dash[[1]]), name="overall average of Tongan notes") %>%
  layout(polar=list(sector=c(20,160), radialaxis=list(angle=90, range=c(0,maximum)), angularaxis=list(thetaunit='radians', direction="clockwise", rotation=0)), title="Overall average smooths for NZE vs Tongan note productions", legend=list(orientation="h", xanchor="center", x=0.5))
p

rm(dat1, dat1_NZE, dat1_Tongan, maximum, smooth_NZE, smooth_Tongan)
LS0tDQp0aXRsZTogIkdBTU1zIGFuYWx5c2VzIFRyb21ib25lIC0gVG9uZ2FuIHZzIEVuZ2xpc2ggKE5aRSkgLT4gSHlwb3RoZXNpcyAxLCBQcmVkaWN0aW9uIDFiIg0KYXV0aG9yOg0KLSBKYWxhbCBBbC1UYW1pbWkgKE5ld2Nhc3RsZSBVbml2ZXJzaXR5KQ0KLSBEb25hbGQgRGVycmljayAoVW5pdmVyc2l0eSBvZiBDYW50ZXJidXJ5KQ0KLSBNYXR0aGlhcyBIZXluZSAoQm9zdG9uIFVuaXZlcnNpdHkpDQpkYXRlOiAiYHIgZm9ybWF0KFN5cy50aW1lKCksICclZCAlQiAlWScpYCINCm91dHB1dDoNCiAgd29yZF9kb2N1bWVudDoNCiAgICB0b2M6IHllcw0KICAgIHRvY19kZXB0aDogJzYnDQogIGh0bWxfbm90ZWJvb2s6DQogICAgbnVtYmVyX3NlY3Rpb25zOiB5ZXMNCiAgICB0b2M6IHllcw0KICAgIHRvY19kZXB0aDogNg0KICAgIHRvY19mbG9hdDoNCiAgICAgIGNvbGxhcHNlZDogeWVzDQogIHBkZl9kb2N1bWVudDoNCiAgICB0b2M6IHllcw0KICAgIHRvY19kZXB0aDogJzYnDQogIGh0bWxfZG9jdW1lbnQ6DQogICAgdG9jOiB5ZXMNCiAgICB0b2NfZGVwdGg6ICc2Jw0KLS0tDQoNClRoaXMgbm90ZWJvb2sgcHJvdmlkZXMgdGhlIGFuYWx5c2lzIHJlZ2FyZGluZyBIeXBvdGhlc2lzIDEsIFByZWRpY3Rpb24gMWIgZm9yIHRoZSBhcnRpY2xlOiBIZXluZSwgTS4sIERlcnJpY2ssIEQuLCBhbmQgQWwtVGFtaW1pLCBKLiAodW5kZXIgcmV2aWV3KS4gIk5hdGl2ZSBsYW5ndWFnZSBpbmZsdWVuY2Ugb24gYnJhc3MgaW5zdHJ1bWVudCBwZXJmb3JtYW5jZTogQW4gYXBwbGljYXRpb24gb2YgZ2VuZXJhbGl6ZWQgYWRkaXRpdmUgbWl4ZWQgbW9kZWxzIChHQU1NcykgdG8gbWlkc2FnaXR0YWwgdWx0cmFzb3VuZCBpbWFnZXMgb2YgdGhlIHRvbmd1ZSIuIEZyb250aWVycyBSZXNlYXJjaCBUb3BpYzogTW9kZWxzIGFuZCBUaGVvcmllcyBvZiBTcGVlY2ggUHJvZHVjdGlvbi4gRWQuIEFkYW1hbnRpb3MgR2Fmb3MgJiBQYXNjYWwgdmFuIExpZXNob3V0Lg0KDQpgYGB7ciB3YXJuaW5nPUZBTFNFLCBtZXNzYWdlPUZBTFNFLCBlcnJvcj1GQUxTRX0NCiMgc3BlY2lmeSBkaXJlY3RvcnkgdG8gc2F2ZSBtb2RlbHMgYW5kIHN1bW1hcmllcw0Kb3V0cHV0X2RpciA9ICJ1cGRhdGVkX21vZGVscyINCg0KIyBzcGVjaWZ5IHdoZXRoZXIgdG8gcnVuIG1vZGVscyAtPiBpZiBzZXQgdG8gZmFsc2Ugc2NyaXB0IHdpbGwgYXR0ZW1wdCB0byBsb2FkIHNhdmVkIG1vZGVscyBmcm9tIG91dHB1dF9kaXINCnJ1bl9tb2RlbHMgPSBGQUxTRQ0KYGBgDQoNCiMgTG9hZGluZyBwYWNrYWdlcw0KDQpgYGB7ciB3YXJuaW5nPUZBTFNFLCBtZXNzYWdlPUZBTFNFLCBlcnJvcj1GQUxTRX0NCmxvYWRfcGFja2FnZXMgPSBjKCJwYXJhbGxlbCIsIm1nY3YiLCAiaXRzYWR1ZyIsICJybGlzdCIsICJnZ3Bsb3QyIiwgInBsb3RseSIsICJkcGx5ciIpDQpmb3IocGtnIGluIGxvYWRfcGFja2FnZXMpew0KICBldmFsKGJxdW90ZShsaWJyYXJ5KC4ocGtnKSkpKQ0KICBpZiAocGFzdGUwKCJwYWNrYWdlOiIsIHBrZykgJWluJSBzZWFyY2goKSl7DQogICAgY2F0KHBhc3RlMCgiU3VjY2Vzc2Z1bGx5IGxvYWRlZCB0aGUgIiwgcGtnLCAiIHBhY2thZ2UuXG4iKSkNCiAgfWVsc2V7DQogICAgaW5zdGFsbC5wYWNrYWdlcyhwa2cpDQogICAgZXZhbChicXVvdGUobGlicmFyeSguKHBrZykpKSkNCiAgICBpZiAocGFzdGUwKCJwYWNrYWdlOiIsIHBrZykgJWluJSBzZWFyY2goKSl7DQogICAgICBjYXQocGFzdGUwKCJTdWNjZXNzZnVsbHkgbG9hZGVkIHRoZSAiLCBwa2csICIgcGFja2FnZS5cbiIpKQ0KICAgIH0NCiAgfQ0KfQ0Kcm0obG9hZF9wYWNrYWdlcywgcGtnKQ0KDQojIGRldGVjdCBudW1iZXIgb2YgY29yZXMgYXZhaWxhYmxlIGZvciBtb2RlbCBjYWxjdWxhdGlvbnMNCm5jb3JlcyA9IGRldGVjdENvcmVzKCkNCmNhdChwYXN0ZTAoIk51bWJlciBvZiBjb3JlcyBhdmFpbGFibGUgZm9yIG1vZGVsIGNhbGN1bGF0aW9ucyBzZXQgdG8gIiwgbmNvcmVzLCAiLiIpKQ0KYGBgDQoNCiMjIyBwbG90bHlfbW9kZWxfb3V0cHV0cyBmdW5jdGlvbiAoTWF0dGhpYXMgSGV5bmUsIDIwMTkpDQoNCmBgYHtyIHdhcm5pbmc9RkFMU0UsIG1lc3NhZ2U9RkFMU0UsIGVycm9yPUZBTFNFfQ0KIyBwbG90IG11bHRpcGxlIEdBTSBtb2RlbCBvdXRwdXRzDQpwbG90bHlfbW9kZWxfb3V0cHV0cyA8LSBmdW5jdGlvbihtb2RlbCwgY2hhbmdpbmdfY29uZCwgY2hhbmdpbmdfdmFyLCBjb25zdGFudF9jb25kMSwgY29uc3RhbnRfdmFyMSwgdmFsdWVzLCBjb25zdGFudF9jb25kMj1OVUxMLCBjb25zdGFudF92YXIyPU5VTEwsIHByaW50PVRSVUUpew0KICBpZihsZW5ndGgoY29uc3RhbnRfdmFyMSk+MSB8IGxlbmd0aChjb25zdGFudF92YXIyKT4xKXsNCiAgICBwcmludCgiRXJyb3I6IENvbnN0YW50IHZhcmlhYmxlcyBjYW4gb25seSBoYXZlIGxlbmd0aCAxLiIpDQogIH1lbHNlew0KICAgIGlmKCFpcy5udWxsKGNvbnN0YW50X2NvbmQyKSAmJiAhaXMubnVsbChjb25zdGFudF92YXIyKSAmJiBsZW5ndGgoY2hhbmdpbmdfdmFyKT09Mil7DQogICAgICAjIHdvcmtzIGZvciBtb2RlbHMgTm90ZXMuZ2FtLi4uDQogICAgICBjb25kX3AxID0gY2FwdHVyZS5vdXRwdXQoY2F0KHBhc3RlMCgibGlzdCgiLCBjaGFuZ2luZ19jb25kLCAiPSciLCBjaGFuZ2luZ192YXJbMV0sICInLCAiLCBjb25zdGFudF9jb25kMSwgIj0nIiwgY29uc3RhbnRfdmFyMSwgIicsICIsIGNvbnN0YW50X2NvbmQyLCAiPSciLCBjb25zdGFudF92YXIyLCAiJykiKSkpDQogICAgICBwMT1wbG90X3Ntb290aCh4PWdldChtb2RlbCksIHZpZXc9dmFsdWVzLCBjb25kID0gZXZhbChwYXJzZSh0ZXh0PWNvbmRfcDEpKSkNCiAgICAgIGNvbmRfcDIgPSBjYXB0dXJlLm91dHB1dChjYXQocGFzdGUwKCJsaXN0KCIsIGNoYW5naW5nX2NvbmQsICI9JyIsIGNoYW5naW5nX3ZhclsyXSwgIicsICIsIGNvbnN0YW50X2NvbmQxLCAiPSciLCBjb25zdGFudF92YXIxLCAiJywgIiwgY29uc3RhbnRfY29uZDIsICI9JyIsIGNvbnN0YW50X3ZhcjIsICInKSIpKSkNCiAgICAgIHAyPXBsb3Rfc21vb3RoKHg9Z2V0KG1vZGVsKSwgdmlldz12YWx1ZXMsIGNvbmQgPSBldmFsKHBhcnNlKHRleHQ9Y29uZF9wMikpKQ0KICAgICAgDQogICAgICAjIHNldCBSaG8gbWF4IHRvIHRoZSBtYXggb2YgdGhlIGZpdCArIGhhbGYgdGhlIGRpZmZlcmVuY2UgYmV0d2VlbiBtYXggb2YgdGhlIGZpdCBhbmQgdGhlIHVwcGVyIGxpbWl0DQogICAgICBtYXhfdWwgPSBtYXgocDEkZnYkdWwsIHAyJGZ2JHVsKQ0KICAgICAgbWF4X2ZpdCA9IG1heChwMSRmdiRmaXQsIHAyJGZ2JGZpdCkNCiAgICAgIG1heGltdW09bWF4X2ZpdCsoKG1heF91bC1tYXhfZml0KS8yKQ0KICAgICAgDQogICAgICAjIHBsb3QgaW4gcG9sYXIgY29vcmRpbmF0ZXMNCiAgICAgIHA9cGxvdF9seSh0eXBlPSdzY2F0dGVycG9sYXInLCBtb2RlPSdsaW5lcycpICU+JSANCiAgICAgICAgYWRkX3RyYWNlKHRoZXRhPXAxJGZ2JHRoZXRhX3VuY3V0X3oqMTgwL3BpLCByPXAxJGZ2JGZpdCwgbGluZT1saXN0KGNvbG9yPSJibHVlIiwgd2lkdGg9Mi41KSwgbmFtZT1jaGFuZ2luZ192YXJbMV0pICU+JSANCiAgICAgICAgYWRkX3RyYWNlKHRoZXRhPXAxJGZ2JHRoZXRhX3VuY3V0X3oqMTgwL3BpLCByPXAxJGZ2JHVsLCBsaW5lPWxpc3QoY29sb3I9ImJsdWUiLCBkYXNoPSJkb3QiLCB3aWR0aD0wLjUpLCBzaG93bGVnZW5kPUZBTFNFKSAlPiUgDQogICAgICAgIGFkZF90cmFjZSh0aGV0YT1wMSRmdiR0aGV0YV91bmN1dF96KjE4MC9waSwgcj1wMSRmdiRsbCwgbGluZT1saXN0KGNvbG9yPSJibHVlIiwgZGFzaD0iZG90Iiwgd2lkdGg9MC41KSwgc2hvd2xlZ2VuZD1GQUxTRSkgJT4lIA0KICAgICAgICBhZGRfdHJhY2UodGhldGE9cDIkZnYkdGhldGFfdW5jdXRfeioxODAvcGksIHI9cDIkZnYkZml0LCBsaW5lPWxpc3QoY29sb3I9InJlZCIsIHdpZHRoPTIuNSksIG5hbWU9Y2hhbmdpbmdfdmFyWzJdKSAlPiUgDQogICAgICAgIGFkZF90cmFjZSh0aGV0YT1wMiRmdiR0aGV0YV91bmN1dF96KjE4MC9waSwgcj1wMiRmdiR1bCwgbGluZT1saXN0KGNvbG9yPSJyZWQiLCBkYXNoPSJkb3QiLCB3aWR0aD0wLjUpLCBzaG93bGVnZW5kPUZBTFNFKSAlPiUgDQogICAgICAgIGFkZF90cmFjZSh0aGV0YT1wMiRmdiR0aGV0YV91bmN1dF96KjE4MC9waSwgcj1wMiRmdiRsbCwgbGluZT1saXN0KGNvbG9yPSJyZWQiLCBkYXNoPSJkb3QiLCB3aWR0aD0wLjUpLCBzaG93bGVnZW5kPUZBTFNFKSAlPiUNCiAgICAgICAgbGF5b3V0KHBvbGFyPWxpc3Qoc2VjdG9yPWMoMjAsMTYwKSwgcmFkaWFsYXhpcz1saXN0KGFuZ2xlPTkwLCByYW5nZT1jKDAsbWF4aW11bSkpLA0KICAgICAgICAgICAgICAgICAgICAgICAgICBhbmd1bGFyYXhpcz1saXN0KHRoZXRhdW5pdD0ncmFkaWFucycsIGRpcmVjdGlvbj0iY2xvY2t3aXNlIiwgcm90YXRpb249MCkpLCANCiAgICAgICAgICAgICAgIHRpdGxlPXBhc3RlMCgiR0FNIHNtb290aHMgQCIsIGNvbnN0YW50X3ZhcjEsICIgJiAiLCBjb25zdGFudF92YXIyKSkNCiAgICAgIHANCiAgICB9ZWxzZSBpZihpcy5udWxsKGNvbnN0YW50X2NvbmQyKSAmJiBpcy5udWxsKGNvbnN0YW50X3ZhcjIpICYmIGxlbmd0aChjaGFuZ2luZ192YXIpPT0yKXsNCiAgICAgICMgbm8gc3BlY2lmaWMgY2FzZSB5ZXQNCiAgICAgIGNvbmRfcDEgPSBjYXB0dXJlLm91dHB1dChjYXQocGFzdGUwKCJsaXN0KCIsIGNoYW5naW5nX2NvbmQsICI9JyIsIGNoYW5naW5nX3ZhclsxXSwgIicsICIsIGNvbnN0YW50X2NvbmQxLCAiPSciLCBjb25zdGFudF92YXIxLCAiJykiKSkpDQogICAgICBwMT1wbG90X3Ntb290aCh4PWdldChtb2RlbCksIHZpZXc9dmFsdWVzLCBjb25kID0gZXZhbChwYXJzZSh0ZXh0PWNvbmRfcDEpKSkNCiAgICAgIGNvbmRfcDIgPSBjYXB0dXJlLm91dHB1dChjYXQocGFzdGUwKCJsaXN0KCIsIGNoYW5naW5nX2NvbmQsICI9JyIsIGNoYW5naW5nX3ZhclsyXSwgIicsICIsIGNvbnN0YW50X2NvbmQxLCAiPSciLCBjb25zdGFudF92YXIxLCAiJykiKSkpDQogICAgICBwMj1wbG90X3Ntb290aCh4PWdldChtb2RlbCksIHZpZXc9dmFsdWVzLCBjb25kID0gZXZhbChwYXJzZSh0ZXh0PWNvbmRfcDIpKSkNCiAgICAgIA0KICAgICAgIyBzZXQgUmhvIG1heCB0byB0aGUgbWF4IG9mIHRoZSBmaXQgKyBoYWxmIHRoZSBkaWZmZXJlbmNlIGJldHdlZW4gbWF4IG9mIHRoZSBmaXQgYW5kIHRoZSB1cHBlciBsaW1pdA0KICAgICAgbWF4X3VsID0gbWF4KHAxJGZ2JHVsLCBwMiRmdiR1bCkNCiAgICAgIG1heF9maXQgPSBtYXgocDEkZnYkZml0LCBwMiRmdiRmaXQpDQogICAgICBtYXhpbXVtPW1heF9maXQrKChtYXhfdWwtbWF4X2ZpdCkvMikNCiAgICAgIA0KICAgICAgIyBwbG90IGluIHBvbGFyIGNvb3JkaW5hdGVzDQogICAgICBwPXBsb3RfbHkodHlwZT0nc2NhdHRlcnBvbGFyJywgbW9kZT0nbGluZXMnKSAlPiUgDQogICAgICAgIGFkZF90cmFjZSh0aGV0YT1wMSRmdiR0aGV0YV91bmN1dF96KjE4MC9waSwgcj1wMSRmdiRmaXQsIGxpbmU9bGlzdChjb2xvcj0iYmx1ZSIsIHdpZHRoPTIuNSksIG5hbWU9Y2hhbmdpbmdfdmFyWzFdKSAlPiUgDQogICAgICAgIGFkZF90cmFjZSh0aGV0YT1wMSRmdiR0aGV0YV91bmN1dF96KjE4MC9waSwgcj1wMSRmdiR1bCwgbGluZT1saXN0KGNvbG9yPSJibHVlIiwgZGFzaD0iZG90Iiwgd2lkdGg9MC41KSwgc2hvd2xlZ2VuZD1GQUxTRSkgJT4lIA0KICAgICAgICBhZGRfdHJhY2UodGhldGE9cDEkZnYkdGhldGFfdW5jdXRfeioxODAvcGksIHI9cDEkZnYkbGwsIGxpbmU9bGlzdChjb2xvcj0iYmx1ZSIsIGRhc2g9ImRvdCIsIHdpZHRoPTAuNSksIHNob3dsZWdlbmQ9RkFMU0UpICU+JSANCiAgICAgICAgYWRkX3RyYWNlKHRoZXRhPXAyJGZ2JHRoZXRhX3VuY3V0X3oqMTgwL3BpLCByPXAyJGZ2JGZpdCwgbGluZT1saXN0KGNvbG9yPSJyZWQiLCB3aWR0aD0yLjUpLCBuYW1lPWNoYW5naW5nX3ZhclsyXSkgJT4lIA0KICAgICAgICBhZGRfdHJhY2UodGhldGE9cDIkZnYkdGhldGFfdW5jdXRfeioxODAvcGksIHI9cDIkZnYkdWwsIGxpbmU9bGlzdChjb2xvcj0icmVkIiwgZGFzaD0iZG90Iiwgd2lkdGg9MC41KSwgc2hvd2xlZ2VuZD1GQUxTRSkgJT4lIA0KICAgICAgICBhZGRfdHJhY2UodGhldGE9cDIkZnYkdGhldGFfdW5jdXRfeioxODAvcGksIHI9cDIkZnYkbGwsIGxpbmU9bGlzdChjb2xvcj0icmVkIiwgZGFzaD0iZG90Iiwgd2lkdGg9MC41KSwgc2hvd2xlZ2VuZD1GQUxTRSkgJT4lDQogICAgICAgIGxheW91dChwb2xhcj1saXN0KHNlY3Rvcj1jKDIwLDE2MCksIHJhZGlhbGF4aXM9bGlzdChhbmdsZT05MCwgcmFuZ2U9YygwLG1heGltdW0pKSwNCiAgICAgICAgICAgICAgICAgICAgICAgICAgYW5ndWxhcmF4aXM9bGlzdCh0aGV0YXVuaXQ9J3JhZGlhbnMnLCBkaXJlY3Rpb249ImNsb2Nrd2lzZSIsIHJvdGF0aW9uPTApKSwgDQogICAgICAgICAgICAgICB0aXRsZT1wYXN0ZTAoIkdBTSBzbW9vdGhzIEAiLCBjb25zdGFudF92YXIxLCAiICYgIiwgY29uc3RhbnRfdmFyMikpDQogICAgICBwDQogICAgfWVsc2UgaWYoaXMubnVsbChjb25zdGFudF9jb25kMikgJiYgaXMubnVsbChjb25zdGFudF92YXIyKSAmJiBsZW5ndGgoY2hhbmdpbmdfdmFyKT4yKXsNCiAgICAgICMgd29ya3MgZm9yIG1vZGVscyBOWkUuZ2FtLi4uIG9yIFRvbmdhbi5nYW0uLi4NCiAgICAgIGZvciAoaSBpbiAxOmxlbmd0aChjaGFuZ2luZ192YXIpKXsNCiAgICAgICAgaWYoY2hhbmdpbmdfY29uZCA9PSBjb25zdGFudF9jb25kMSl7DQogICAgICAgICAgY29uZF9wMSA9IGNhcHR1cmUub3V0cHV0KGNhdChwYXN0ZTAoImxpc3QoIiwgY29uc3RhbnRfY29uZDEsICI9JyIsIGNvbnN0YW50X3ZhcjEsICInKSIpKSkNCiAgICAgICAgICBwMT1wbG90X3Ntb290aCh4PWdldChtb2RlbCksIHZpZXc9dmFsdWVzLCBjb25kID0gZXZhbChwYXJzZSh0ZXh0PWNvbmRfcDEpKSkNCiAgICAgICAgICAjIGV4Y2VwdGlvbiBmb3IgS0lUICg9J1xcXFwnKSB3aGVuIG5vdCB1c2luZyBJUEEgc3ltYm9scw0KICAgICAgICAgIGlmIChjaGFuZ2luZ192YXJbaV0hPSJcXFxcIil7DQogICAgICAgICAgICBjb25kX3AyID0gY2FwdHVyZS5vdXRwdXQoY2F0KHBhc3RlMCgibGlzdCgiLCBjaGFuZ2luZ19jb25kLCAiPSciLCBjaGFuZ2luZ192YXJbaV0sICInKSIpKSkNCiAgICAgICAgICAgIHAyPXBsb3Rfc21vb3RoKHg9Z2V0KG1vZGVsKSwgdmlldz12YWx1ZXMsIGNvbmQgPSBldmFsKHBhcnNlKHRleHQ9Y29uZF9wMikpKQ0KICAgICAgICAgIH1lbHNlew0KICAgICAgICAgICAgcDI9cGxvdF9zbW9vdGgoeD1nZXQobW9kZWwpLCB2aWV3PXZhbHVlcywgY29uZCA9IGxpc3QodG9rZW4ub3JkPSdcXFxcJykpDQogICAgICAgICAgfQ0KICAgICAgICAgIA0KICAgICAgICAgICMgc2V0IFJobyBtYXggdG8gdGhlIG1heCBvZiB0aGUgZml0ICsgaGFsZiB0aGUgZGlmZmVyZW5jZSBiZXR3ZWVuIG1heCBvZiB0aGUgZml0IGFuZCB0aGUgdXBwZXIgbGltaXQNCiAgICAgICAgICBtYXhfdWwgPSBtYXgocDEkZnYkdWwsIHAyJGZ2JHVsKQ0KICAgICAgICAgIG1heF9maXQgPSBtYXgocDEkZnYkZml0LCBwMiRmdiRmaXQpDQogICAgICAgICAgbWF4aW11bT1tYXhfZml0KygobWF4X3VsLW1heF9maXQpLzIpDQoNCiAgICAgICAgICAjIHBsb3QgaW4gcG9sYXIgY29vcmRpbmF0ZXMNCiAgICAgICAgICBwPXBsb3RfbHkodHlwZT0nc2NhdHRlcnBvbGFyJywgbW9kZT0nbGluZXMnKSAlPiUgDQogICAgICAgICAgICBhZGRfdHJhY2UodGhldGE9cDEkZnYkdGhldGFfdW5jdXRfeioxODAvcGksIHI9cDEkZnYkZml0LCBsaW5lPWxpc3QoY29sb3I9ImJsdWUiLCB3aWR0aD0yLjUpLCBuYW1lPWNvbnN0YW50X3ZhcjEpICU+JSANCiAgICAgICAgICAgIGFkZF90cmFjZSh0aGV0YT1wMSRmdiR0aGV0YV91bmN1dF96KjE4MC9waSwgcj1wMSRmdiR1bCwgbGluZT1saXN0KGNvbG9yPSJibHVlIiwgZGFzaD0iZG90Iiwgd2lkdGg9MC41KSwgc2hvd2xlZ2VuZD1GQUxTRSkgJT4lIA0KICAgICAgICAgICAgYWRkX3RyYWNlKHRoZXRhPXAxJGZ2JHRoZXRhX3VuY3V0X3oqMTgwL3BpLCByPXAxJGZ2JGxsLCBsaW5lPWxpc3QoY29sb3I9ImJsdWUiLCBkYXNoPSJkb3QiLCB3aWR0aD0wLjUpLCBzaG93bGVnZW5kPUZBTFNFKSAlPiUgDQogICAgICAgICAgICBhZGRfdHJhY2UodGhldGE9cDIkZnYkdGhldGFfdW5jdXRfeioxODAvcGksIHI9cDIkZnYkZml0LCBsaW5lPWxpc3QoY29sb3I9InJlZCIsIHdpZHRoPTIuNSksIG5hbWU9Y2hhbmdpbmdfdmFyW2ldKSAlPiUgDQogICAgICAgICAgICBhZGRfdHJhY2UodGhldGE9cDIkZnYkdGhldGFfdW5jdXRfeioxODAvcGksIHI9cDIkZnYkdWwsIGxpbmU9bGlzdChjb2xvcj0icmVkIiwgZGFzaD0iZG90Iiwgd2lkdGg9MC41KSwgc2hvd2xlZ2VuZD1GQUxTRSkgJT4lIA0KICAgICAgICAgICAgYWRkX3RyYWNlKHRoZXRhPXAyJGZ2JHRoZXRhX3VuY3V0X3oqMTgwL3BpLCByPXAyJGZ2JGxsLCBsaW5lPWxpc3QoY29sb3I9InJlZCIsIGRhc2g9ImRvdCIsIHdpZHRoPTAuNSksIHNob3dsZWdlbmQ9RkFMU0UpICU+JQ0KICAgICAgICAgICAgbGF5b3V0KHBvbGFyPWxpc3Qoc2VjdG9yPWMoMjAsMTYwKSwgcmFkaWFsYXhpcz1saXN0KGFuZ2xlPTkwLCByYW5nZT1jKDAsbWF4aW11bSkpLA0KICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgYW5ndWxhcmF4aXM9bGlzdCh0aGV0YXVuaXQ9J3JhZGlhbnMnLCBkaXJlY3Rpb249ImNsb2Nrd2lzZSIsIHJvdGF0aW9uPTApKSwgDQogICAgICAgICAgICAgICAgICAgdGl0bGU9cGFzdGUwKCJHQU0gc21vb3RocyAiLGNvbnN0YW50X3ZhcjEsIiB2cyAiLCBjaGFuZ2luZ192YXJbaV0pKQ0KICAgICAgICAgIFN5cy5zbGVlcCgwKQ0KICAgICAgICAgIHByaW50KHApDQogICAgICAgIH0NCiAgICAgIH0NCiAgICB9DQogIH0NCn0NCmBgYA0KDQojIyMgcGxvdGx5X3NpZ19kaWZmX25vdGVzIGZ1bmN0aW9uIChNYXR0aGlhcyBIZXluZSwgMjAxOSkgLT4gd2l0aCB1cGRhdGVkIGxlZ2VuZCBwb3NpdGlvbg0KDQpgYGB7ciB3YXJuaW5nPUZBTFNFLCBtZXNzYWdlPUZBTFNFLCBlcnJvcj1GQUxTRX0NCiMgcGxvdCBzbW9vdGhzIHdpdGggc2hhZGluZyB0byBpbmRpY2F0ZSBzaWduaWZpY2FudCBkaWZmZXJlbmNlcyAoTWF0dGhpYXMgSGV5bmUsIDIwMTkpDQpwbG90bHlfc21vb3Roc193X3NpZ19kaWZmIDwtIGZ1bmN0aW9uKG1vZGVsLCBjb25kaXRpb24sIHZhcjEsIHZhcjIsIHZhbHVlcywgbGFuZ3VhZ2UsIHByaW50PVRSVUUpew0KICAjIGdldCBpbnRlcnZhbHMgb2Ygc2lnbmlmaWNhbnQgZGlmZmVyZW5jZXMgYnkgcnVubmluZyBwbG90X2RpZmYNCiAgIyB1bmZvcnR1bmF0ZWx5IHNldHRpbmcgcGxvdD1GQUxTRSBkb2Vzbid0IHdvcmsgYXMgaW50ZXJ2YWxzIG9mIHNpZ25pZmljYW50IGRpZmZlcmVuY2UgYXJlIG5vdCBkaXNwbGF5ZWQhDQogICMgaGFyZGNvZGVkIGNvbmRpdGlvbg0KICAjIG91dHB1dCA9IGNhcHR1cmUub3V0cHV0KHBsb3RfZGlmZihnZXQobW9kZWwpLCB2aWV3PXZhbHVlcywgDQogICMgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIGNvbXA9bGlzdCh0b2tlblBvb2xlZC5vcmQ9Yyh2YXIxLCB2YXIyKSkpKQ0KICAjIG91dHB1dCA9IGNhcHR1cmUub3V0cHV0KHBsb3RfZGlmZihnZXQobW9kZWwpLCB2aWV3PXZhbHVlcywgY29tcD1saXN0KGxhbmdOb3RlSW50Lm9yZD1jKHBhc3RlMCgiVG9uZ2FuLiIsIG5vdGUsICIuIiwgaW50ZW5zaXR5KSwgcGFzdGUwKCJOWkUuIiwgbm90ZSwgIi4iLCBpbnRlbnNpdHkpKSkpKQ0KICBuYW1lc19zbW9vdGhzPWxpc3QoKQ0KICBpZiAoY29uZGl0aW9uPT0idG9rZW5Qb29sZWQub3JkIiAmJiBsZW5ndGgobGFuZ3VhZ2UpPT0xKXsNCiAgICBvdXRwdXRfY29tcCA9IGNhcHR1cmUub3V0cHV0KGNhdChwYXN0ZTAoImxpc3QoIiwgY29uZGl0aW9uLCAiPWModmFyMSwgdmFyMikpIikpKQ0KICAgIG5hbWVzX3Ntb290aHNbMV09dmFyMQ0KICAgIG5hbWVzX3Ntb290aHNbMl09dmFyMg0KICAgIHBsb3RfdGl0bGUgPSBwYXN0ZTAoIkdBTSBzbW9vdGhzICIsIGxhbmd1YWdlLCAiICIsIHZhcjEsICIgdnMgIiwgdmFyMikNCiAgfWVsc2UgaWYgKGNvbmRpdGlvbj09ImxhbmdOb3RlSW50Lm9yZCIgJiYgbGVuZ3RoKGxhbmd1YWdlKT09Mil7DQogICAgb3V0cHV0X2NvbXAgPSBjYXB0dXJlLm91dHB1dChjYXQocGFzdGUwKCJsaXN0KCIsIGNvbmRpdGlvbiwgIj1jKCciLCBsYW5ndWFnZVsxXSwgIi4iLCB2YXIxLCAiLiIsIHZhcjIsIA0KICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAiJywgJyIsIGxhbmd1YWdlWzJdLCAiLiIsIHZhcjEsICIuIiwgdmFyMiwgIicpKSIpKSkNCiAgICBuYW1lc19zbW9vdGhzWzFdPXBhc3RlMChsYW5ndWFnZVsxXSwgIi4iLCB2YXIxLCAiLiIsIHZhcjIpDQogICAgbmFtZXNfc21vb3Roc1syXT1wYXN0ZTAobGFuZ3VhZ2VbMl0sICIuIiwgdmFyMSwgIi4iLCB2YXIyKQ0KICAgIHBsb3RfdGl0bGUgPSBwYXN0ZTAoIkdBTSBzbW9vdGhzICIsIGxhbmd1YWdlWzFdLCAiLiIsIHZhcjEsICIuIiwgdmFyMiwgIiB2cyAiLCBsYW5ndWFnZVsyXSwgIi4iLCB2YXIxLCAiLiIsIHZhcjIpDQogIH1lbHNlIGlmIChjb25kaXRpb249PSJuYXRpdmVfbGcub3JkIil7DQogICAgb3V0cHV0X2NvbXAgPSBjYXB0dXJlLm91dHB1dChjYXQocGFzdGUwKCJsaXN0KCIsIGNvbmRpdGlvbiwgIj1jKHZhcjEsIHZhcjIpKSIpKSkNCiAgICBuYW1lc19zbW9vdGhzWzFdPXZhcjENCiAgICBuYW1lc19zbW9vdGhzWzJdPXZhcjINCiAgICBwbG90X3RpdGxlID0gcGFzdGUwKCJHQU0gc21vb3RocyAiLCBsYW5ndWFnZSwgIiAiLCB2YXIxLCAiIHZzICIsIHZhcjIpDQogIH0NCiAgDQogICMgb3V0cHV0X2NvbXAgPSBjYXB0dXJlLm91dHB1dChjYXQocGFzdGUwKCJsaXN0KCIsIGNvbmRpdGlvbiwgIj1jKHZhcjEsIHZhcjIpKSIpKSkNCiAgb3V0cHV0ID0gY2FwdHVyZS5vdXRwdXQocGxvdF9kaWZmKGdldChtb2RlbCksIHZpZXc9dmFsdWVzLCBjb21wPWV2YWwocGFyc2UodGV4dD1vdXRwdXRfY29tcCkpKSkNCiAgIyBubyBzaWduaWZpY2FudCBkaWZmZXJlbmNlDQogIGlmICgobGVuZ3RoKGxhbmd1YWdlKT09MSAmJiBsZW5ndGgob3V0cHV0KT09NykgfCAobGVuZ3RoKGxhbmd1YWdlKT09MiAmJiBsZW5ndGgob3V0cHV0KT09Nikpew0KICAgIGNhdChwYXN0ZTAoIlNtb290aHMgZm9yICIsIHZhcjEsICIgJiAiLCB2YXIyLCAiIGFyZSBub3Qgc2lnbmlmaWNhbnRseSBkaWZmZXJlbnQuXG4iKSkNCiAgICBkYXQxID0gTkENCiAgICBhc3NpZ24ocGFzdGUwKCJpbnRfc2lnX2RpZmZfIiwgdmFyMSwgIl8iLCB2YXIyKSwgZGF0MSwgZW52aXIgPSAuR2xvYmFsRW52KQ0KICAgIHJtKGRhdDEpDQogICAgIyBydW4gcGxvdF9zbW9vdGggdG8gZ3JhYiBkYXRhIGZvciBwb2xhciBwbG90cw0KICAgIHAxID0gcGxvdF9zbW9vdGgoeD1nZXQobW9kZWwpLCB2aWV3PXZhbHVlcywgY29uZD1saXN0KHRva2VuUG9vbGVkLm9yZD12YXIxLCB0b2tlblBvb2xlZC5vcmQ9dmFyMikpDQogICAgcDIgPSBwbG90X3Ntb290aCh4PWdldChtb2RlbCksIHZpZXc9dmFsdWVzLCBjb25kPWxpc3QodG9rZW5Qb29sZWQub3JkPXZhcjIsIHRva2VuUG9vbGVkLm9yZD12YXIxKSkNCiAgICAjIHNldCBSaG8gbWF4IHRvIHRoZSBtYXggb2YgdGhlIGZpdCArIGhhbGYgdGhlIGRpZmZlcmVuY2UgYmV0d2VlbiBtYXggb2YgdGhlIGZpdCBhbmQgdGhlIHVwcGVyIGxpbWl0DQogICAgbWF4aW11bT1tYXgocDEkZnYkZml0LCBwMiRmdiRmaXQpKygobWF4KHAxJGZ2JHVsLCBwMiRmdiR1bCktbWF4KHAxJGZ2JGZpdCwgcDIkZnYkZml0KSkvMikNCiAgICAjIHBsb3QgaW4gcG9sYXIgY29vcmRpbmF0ZXMNCiAgICBwPXBsb3RfbHkodHlwZT0nc2NhdHRlcnBvbGFyJywgbW9kZT0nbGluZXMnKSAlPiUgDQogICAgICBhZGRfdHJhY2UodGhldGE9cDEkZnYkdGhldGFfdW5jdXRfeioxODAvcGksIHI9cDEkZnYkZml0LCBsaW5lPWxpc3QoY29sb3I9ImJsdWUiLCB3aWR0aD0yLjUpLCBuYW1lPW5hbWVzX3Ntb290aHNbMV0pICU+JSANCiAgICAgIGFkZF90cmFjZSh0aGV0YT1wMSRmdiR0aGV0YV91bmN1dF96KjE4MC9waSwgcj1wMSRmdiR1bCwgbGluZT1saXN0KGNvbG9yPSJibHVlIiwgZGFzaD0iZG90Iiwgd2lkdGg9MC41KSwgc2hvd2xlZ2VuZD1GQUxTRSkgJT4lIA0KICAgICAgYWRkX3RyYWNlKHRoZXRhPXAxJGZ2JHRoZXRhX3VuY3V0X3oqMTgwL3BpLCByPXAxJGZ2JGxsLCBsaW5lPWxpc3QoY29sb3I9ImJsdWUiLCBkYXNoPSJkb3QiLCB3aWR0aD0wLjUpLCBzaG93bGVnZW5kPUZBTFNFKSAlPiUgDQogICAgICBhZGRfdHJhY2UodGhldGE9cDIkZnYkdGhldGFfdW5jdXRfeioxODAvcGksIHI9cDIkZnYkZml0LCBsaW5lPWxpc3QoY29sb3I9InJlZCIsIHdpZHRoPTIuNSksIG5hbWU9bmFtZXNfc21vb3Roc1syXSkgJT4lIA0KICAgICAgYWRkX3RyYWNlKHRoZXRhPXAyJGZ2JHRoZXRhX3VuY3V0X3oqMTgwL3BpLCByPXAyJGZ2JHVsLCBsaW5lPWxpc3QoY29sb3I9InJlZCIsIGRhc2g9ImRvdCIsIHdpZHRoPTAuNSksIHNob3dsZWdlbmQ9RkFMU0UpICU+JSANCiAgICAgIGFkZF90cmFjZSh0aGV0YT1wMiRmdiR0aGV0YV91bmN1dF96KjE4MC9waSwgcj1wMiRmdiRsbCwgbGluZT1saXN0KGNvbG9yPSJyZWQiLCBkYXNoPSJkb3QiLCB3aWR0aD0wLjUpLCBzaG93bGVnZW5kPUZBTFNFKSAlPiUNCiAgICAgIGxheW91dChwb2xhcj1saXN0KHNlY3Rvcj1jKDIwLDE2MCksIHJhZGlhbGF4aXM9bGlzdChhbmdsZT05MCwgcmFuZ2U9YygwLG1heGltdW0pKSwNCiAgICAgICAgICAgICAgICAgICAgICAgIGFuZ3VsYXJheGlzPWxpc3QodGhldGF1bml0PSdyYWRpYW5zJywgZGlyZWN0aW9uPSJjbG9ja3dpc2UiLCByb3RhdGlvbj0wKSksIA0KICAgICAgICAgICAgIHRpdGxlPXBsb3RfdGl0bGUsIGxlZ2VuZD1saXN0KG9yaWVudGF0aW9uPSJoIiwgeGFuY2hvcj0iY2VudGVyIiwgeD0wLjUpKQ0KICAgIFN5cy5zbGVlcCgwKQ0KICAgIHByaW50KHApDQogICMgdGhlcmUgYXJlIGRpZmZlcmVuY2VzLi4uDQogIH1lbHNlew0KICAgICMgZ3JhYiBpbnRlcnZhbHMgb2Ygc2lnbmlmaWNhbnQgZGlmZmVyZW5jZXMgZnJvbSBvdXRwdXQNCiAgICBpZiAobGVuZ3RoKGxhbmd1YWdlKT09MSAmJiBsZW5ndGgob3V0cHV0KT49OCl7DQogICAgICBzaWdfZGlmZjEgPSBjKGFzLmRvdWJsZSh1bmxpc3Qoc3Ryc3BsaXQodW5saXN0KHN0cnNwbGl0KG91dHB1dFs4XSwgIiAiKSlbMV0sICJcdCIpKVsyXSksIGFzLmRvdWJsZSh1bmxpc3Qoc3Ryc3BsaXQob3V0cHV0WzhdLCAiICIpKVszXSkpDQogICAgfWVsc2UgaWYgKGxlbmd0aChsYW5ndWFnZSk9PTIgJiYgbGVuZ3RoKG91dHB1dCk+PTcpew0KICAgICAgc2lnX2RpZmYxID0gYyhhcy5kb3VibGUodW5saXN0KHN0cnNwbGl0KHVubGlzdChzdHJzcGxpdChvdXRwdXRbN10sICIgIikpWzFdLCAiXHQiKSlbMl0pLCBhcy5kb3VibGUodW5saXN0KHN0cnNwbGl0KG91dHB1dFs3XSwgIiAiKSlbM10pKQ0KICAgIH0NCiAgICBpZiAobGVuZ3RoKGxhbmd1YWdlKT09MSAmJiBsZW5ndGgob3V0cHV0KT49OSl7DQogICAgICBzaWdfZGlmZjIgPSBjKGFzLmRvdWJsZSh1bmxpc3Qoc3Ryc3BsaXQodW5saXN0KHN0cnNwbGl0KG91dHB1dFs5XSwgIiAiKSlbMV0sICJcdCIpKVsyXSksIGFzLmRvdWJsZSh1bmxpc3Qoc3Ryc3BsaXQob3V0cHV0WzldLCAiICIpKVszXSkpDQogICAgfWVsc2UgaWYgKGxlbmd0aChsYW5ndWFnZSk9PTIgJiYgbGVuZ3RoKG91dHB1dCk+PTgpew0KICAgICAgc2lnX2RpZmYyID0gYyhhcy5kb3VibGUodW5saXN0KHN0cnNwbGl0KHVubGlzdChzdHJzcGxpdChvdXRwdXRbOF0sICIgIikpWzFdLCAiXHQiKSlbMl0pLCBhcy5kb3VibGUodW5saXN0KHN0cnNwbGl0KG91dHB1dFs4XSwgIiAiKSlbM10pKQ0KICAgIH0NCiAgICBpZiAobGVuZ3RoKGxhbmd1YWdlKT09MSAmJiBsZW5ndGgob3V0cHV0KT49MTApew0KICAgICAgc2lnX2RpZmYzID0gYyhhcy5kb3VibGUodW5saXN0KHN0cnNwbGl0KHVubGlzdChzdHJzcGxpdChvdXRwdXRbMTBdLCAiICIpKVsxXSwgIlx0IikpWzJdKSwgYXMuZG91YmxlKHVubGlzdChzdHJzcGxpdChvdXRwdXRbMTBdLCAiICIpKVszXSkpDQogICAgfWVsc2UgaWYgKGxlbmd0aChsYW5ndWFnZSk9PTIgJiYgbGVuZ3RoKG91dHB1dCk+PTkpew0KICAgICAgc2lnX2RpZmYzID0gYyhhcy5kb3VibGUodW5saXN0KHN0cnNwbGl0KHVubGlzdChzdHJzcGxpdChvdXRwdXRbOV0sICIgIikpWzFdLCAiXHQiKSlbMl0pLCBhcy5kb3VibGUodW5saXN0KHN0cnNwbGl0KG91dHB1dFs5XSwgIiAiKSlbM10pKQ0KICAgIH0NCiAgICBpZiAobGVuZ3RoKGxhbmd1YWdlKT09MSAmJiBsZW5ndGgob3V0cHV0KT49MTEpew0KICAgICAgc2lnX2RpZmY0ID0gYyhhcy5kb3VibGUodW5saXN0KHN0cnNwbGl0KHVubGlzdChzdHJzcGxpdChvdXRwdXRbMTFdLCAiICIpKVsxXSwgIlx0IikpWzJdKSwgYXMuZG91YmxlKHVubGlzdChzdHJzcGxpdChvdXRwdXRbMTFdLCAiICIpKVszXSkpDQogICAgfWVsc2UgaWYgKGxlbmd0aChsYW5ndWFnZSk9PTIgJiYgbGVuZ3RoKG91dHB1dCk+PTEwKXsNCiAgICAgIHNpZ19kaWZmNCA9IGMoYXMuZG91YmxlKHVubGlzdChzdHJzcGxpdCh1bmxpc3Qoc3Ryc3BsaXQob3V0cHV0WzEwXSwgIiAiKSlbMV0sICJcdCIpKVsyXSksIGFzLmRvdWJsZSh1bmxpc3Qoc3Ryc3BsaXQob3V0cHV0WzEwXSwgIiAiKSlbM10pKQ0KICAgIH0NCiAgICAjIHdyaXRlIGludGVydmFscyBvZiBzaWduaWZpY2FudCBkaWZmZXJlbmNlIHRvIHZhcmlhYmxlDQogICAgaWYgKChsZW5ndGgobGFuZ3VhZ2UpPT0xICYmIGxlbmd0aChvdXRwdXQpPj0xMSkgfCAobGVuZ3RoKGxhbmd1YWdlKT09MiAmJiBsZW5ndGgob3V0cHV0KT49MTApKXsNCiAgICAgIGRhdDEgPSBjKHNpZ19kaWZmMSwgc2lnX2RpZmYyLCBzaWdfZGlmZjMsIHNpZ19kaWZmNCkNCiAgICB9ZWxzZSBpZiAoKGxlbmd0aChsYW5ndWFnZSk9PTEgJiYgbGVuZ3RoKG91dHB1dCk+PTEwKSB8IChsZW5ndGgobGFuZ3VhZ2UpPT0yICYmIGxlbmd0aChvdXRwdXQpPj05KSl7DQogICAgICBkYXQxID0gYyhzaWdfZGlmZjEsIHNpZ19kaWZmMiwgc2lnX2RpZmYzKQ0KICAgIH1lbHNlIGlmICgobGVuZ3RoKGxhbmd1YWdlKT09MSAmJiBsZW5ndGgob3V0cHV0KT49OSkgfCAobGVuZ3RoKGxhbmd1YWdlKT09MiAmJiBsZW5ndGgob3V0cHV0KT49OCkpew0KICAgICAgZGF0MSA9IGMoc2lnX2RpZmYxLCBzaWdfZGlmZjIpDQogICAgfWVsc2V7DQogICAgICBkYXQxID0gc2lnX2RpZmYxDQogICAgfQ0KICAgIGFzc2lnbihwYXN0ZTAoImludF9zaWdfZGlmZl8iLCB2YXIxLCAiXyIsIHZhcjIpLCBkYXQxLCBlbnZpciA9IC5HbG9iYWxFbnYpDQogICAgcm0oZGF0MSwgb3V0cHV0KQ0KICAgICMgcnVuIHBsb3Rfc21vb3RoIHRvIGdyYWIgZGF0YSBmb3IgcG9sYXIgcGxvdHMNCiAgICBpZiAoY29uZGl0aW9uPT0idG9rZW5Qb29sZWQub3JkIiAmJiBsZW5ndGgobGFuZ3VhZ2UpPT0xKXsNCiAgICAgIGNvbmRfcDEgPSBjYXB0dXJlLm91dHB1dChjYXQocGFzdGUwKCJsaXN0KCIsIGNvbmRpdGlvbiwgIj12YXIxKSIpKSkNCiAgICAgIGNvbmRfcDIgPSBjYXB0dXJlLm91dHB1dChjYXQocGFzdGUwKCJsaXN0KCIsIGNvbmRpdGlvbiwgIj12YXIyKSIpKSkNCiAgICB9ZWxzZSBpZiAoY29uZGl0aW9uPT0ibGFuZ05vdGVJbnQub3JkIiAmJiBsZW5ndGgobGFuZ3VhZ2UpPT0yKXsNCiAgICAgIGNvbmRfcDEgPSBjYXB0dXJlLm91dHB1dChjYXQocGFzdGUwKCJsaXN0KCIsIGNvbmRpdGlvbiwgIj0nIiwgbGFuZ3VhZ2VbMV0sICIuIiwgdmFyMSwgIi4iLCB2YXIyLCANCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIicsICIsIGNvbmRpdGlvbiwgIj0nIiwgbGFuZ3VhZ2VbMl0sICIuIiwgdmFyMSwgIi4iLCB2YXIyLCAiJykiKSkpDQogICAgICBjb25kX3AyID0gY2FwdHVyZS5vdXRwdXQoY2F0KHBhc3RlMCgibGlzdCgiLCBjb25kaXRpb24sICI9JyIsIGxhbmd1YWdlWzJdLCAiLiIsIHZhcjEsICIuIiwgdmFyMiwgDQogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAiJywgIiwgY29uZGl0aW9uLCAiPSciLCBsYW5ndWFnZVsxXSwgIi4iLCB2YXIxLCAiLiIsIHZhcjIsICInKSIpKSkNCiAgICB9ZWxzZSBpZiAoY29uZGl0aW9uPT0ibmF0aXZlX2xnLm9yZCIpew0KICAgICAgY29uZF9wMSA9IGNhcHR1cmUub3V0cHV0KGNhdChwYXN0ZTAoImxpc3QoIiwgY29uZGl0aW9uLCAiPXZhcjEpIikpKQ0KICAgICAgY29uZF9wMiA9IGNhcHR1cmUub3V0cHV0KGNhdChwYXN0ZTAoImxpc3QoIiwgY29uZGl0aW9uLCAiPXZhcjIpIikpKQ0KICAgIH0NCiAgICAjIGhhcmRjb2RlZCBjb25kaXRpb24NCiAgICBwMSA9IHBsb3Rfc21vb3RoKHg9Z2V0KG1vZGVsKSwgdmlldz12YWx1ZXMsIGNvbmQ9ZXZhbChwYXJzZSh0ZXh0PWNvbmRfcDEpKSkNCiAgICBwMiA9IHBsb3Rfc21vb3RoKHg9Z2V0KG1vZGVsKSwgdmlldz12YWx1ZXMsIGNvbmQ9ZXZhbChwYXJzZSh0ZXh0PWNvbmRfcDIpKSkNCiAgICAjIHNldCBSaG8gbWF4IHRvIHRoZSBtYXggb2YgdGhlIGZpdCArIGhhbGYgdGhlIGRpZmZlcmVuY2UgYmV0d2VlbiBtYXggb2YgdGhlIGZpdCBhbmQgdGhlIHVwcGVyIGxpbWl0DQogICAgbWF4aW11bT1tYXgocDEkZnYkZml0LCBwMiRmdiRmaXQpKygobWF4KHAxJGZ2JHVsLCBwMiRmdiR1bCktbWF4KHAxJGZ2JGZpdCwgcDIkZnYkZml0KSkvMikNCiAgICAjIHBsb3QgaW4gcG9sYXIgY29vcmRpbmF0ZXMNCiAgICBpZiAoZXhpc3RzKCJzaWdfZGlmZjQiKSl7DQogICAgICBwPXBsb3RfbHkodHlwZT0nc2NhdHRlcnBvbGFyJywgbW9kZT0nbGluZXMnKSAlPiUgDQogICAgICAgIGFkZF90cmFjZSh0aGV0YT1wMSRmdiR0aGV0YV91bmN1dF96KjE4MC9waSwgcj1wMSRmdiRmaXQsIGxpbmU9bGlzdChjb2xvcj0iYmx1ZSIsIHdpZHRoPTIuNSksIG5hbWU9bmFtZXNfc21vb3Roc1sxXSkgJT4lIA0KICAgICAgICBhZGRfdHJhY2UodGhldGE9cDEkZnYkdGhldGFfdW5jdXRfeioxODAvcGksIHI9cDEkZnYkdWwsIGxpbmU9bGlzdChjb2xvcj0iYmx1ZSIsIGRhc2g9ImRvdCIsIHdpZHRoPTAuNSksIHNob3dsZWdlbmQ9RkFMU0UpICU+JSANCiAgICAgICAgYWRkX3RyYWNlKHRoZXRhPXAxJGZ2JHRoZXRhX3VuY3V0X3oqMTgwL3BpLCByPXAxJGZ2JGxsLCBsaW5lPWxpc3QoY29sb3I9ImJsdWUiLCBkYXNoPSJkb3QiLCB3aWR0aD0wLjUpLCBzaG93bGVnZW5kPUZBTFNFKSAlPiUgDQogICAgICAgIGFkZF90cmFjZSh0aGV0YT1wMiRmdiR0aGV0YV91bmN1dF96KjE4MC9waSwgcj1wMiRmdiRmaXQsIGxpbmU9bGlzdChjb2xvcj0icmVkIiwgd2lkdGg9Mi41KSwgbmFtZT1uYW1lc19zbW9vdGhzWzJdKSAlPiUgDQogICAgICAgIGFkZF90cmFjZSh0aGV0YT1wMiRmdiR0aGV0YV91bmN1dF96KjE4MC9waSwgcj1wMiRmdiR1bCwgbGluZT1saXN0KGNvbG9yPSJyZWQiLCBkYXNoPSJkb3QiLCB3aWR0aD0wLjUpLCBzaG93bGVnZW5kPUZBTFNFKSAlPiUgDQogICAgICAgIGFkZF90cmFjZSh0aGV0YT1wMiRmdiR0aGV0YV91bmN1dF96KjE4MC9waSwgcj1wMiRmdiRsbCwgbGluZT1saXN0KGNvbG9yPSJyZWQiLCBkYXNoPSJkb3QiLCB3aWR0aD0wLjUpLCBzaG93bGVnZW5kPUZBTFNFKSAlPiUNCiAgICAgICAgYWRkX3RyYWNlKHRoZXRhPXNlcShzaWdfZGlmZjFbMV0qMTgwL3BpLCBzaWdfZGlmZjFbMl0qMTgwL3BpLCBsZW5ndGgub3V0PTIwKSwgDQogICAgICAgICAgICAgICAgICByPWMoMCwgcmVwKG1heGltdW0sIDE4KSwgMCksIGxpbmU9bGlzdChjb2xvcj0iYmxhY2siLCB3aWR0aD0wLjUpLCBmaWxsPSJ0b3NlbGYiLCBmaWxsY29sb3I9cmdiKDAsMCwwLG1heD0yNTUsYWxwaGE9MjUpLCBzaG93bGVnZW5kPUZBTFNFKSAlPiUNCiAgICAgICAgYWRkX3RyYWNlKHRoZXRhPXNlcShzaWdfZGlmZjJbMV0qMTgwL3BpLCBzaWdfZGlmZjJbMl0qMTgwL3BpLCBsZW5ndGgub3V0PTIwKSwgDQogICAgICAgICAgICAgICAgICByPWMoMCwgcmVwKG1heGltdW0sIDE4KSwgMCksIGxpbmU9bGlzdChjb2xvcj0iYmxhY2siLCB3aWR0aD0wLjUpLCBmaWxsPSJ0b3NlbGYiLCBmaWxsY29sb3I9cmdiKDAsMCwwLG1heD0yNTUsYWxwaGE9MjUpLCBzaG93bGVnZW5kPUZBTFNFKSAlPiUNCiAgICAgICAgYWRkX3RyYWNlKHRoZXRhPXNlcShzaWdfZGlmZjNbMV0qMTgwL3BpLCBzaWdfZGlmZjNbMl0qMTgwL3BpLCBsZW5ndGgub3V0PTIwKSwgDQogICAgICAgICAgICAgICAgICByPWMoMCwgcmVwKG1heGltdW0sIDE4KSwgMCksIGxpbmU9bGlzdChjb2xvcj0iYmxhY2siLCB3aWR0aD0wLjUpLCBmaWxsPSJ0b3NlbGYiLCBmaWxsY29sb3I9cmdiKDAsMCwwLG1heD0yNTUsYWxwaGE9MjUpLCBzaG93bGVnZW5kPUZBTFNFKSAlPiUNCiAgICAgICAgYWRkX3RyYWNlKHRoZXRhPXNlcShzaWdfZGlmZjRbMV0qMTgwL3BpLCBzaWdfZGlmZjRbMl0qMTgwL3BpLCBsZW5ndGgub3V0PTIwKSwgDQogICAgICAgICAgICAgICAgICByPWMoMCwgcmVwKG1heGltdW0sIDE4KSwgMCksIGxpbmU9bGlzdChjb2xvcj0iYmxhY2siLCB3aWR0aD0wLjUpLCBmaWxsPSJ0b3NlbGYiLCBmaWxsY29sb3I9cmdiKDAsMCwwLG1heD0yNTUsYWxwaGE9MjUpLCBzaG93bGVnZW5kPUZBTFNFKSAlPiUNCiAgICAgICAgbGF5b3V0KHBvbGFyPWxpc3Qoc2VjdG9yPWMoMjAsMTYwKSwgcmFkaWFsYXhpcz1saXN0KGFuZ2xlPTkwLCByYW5nZT1jKDAsbWF4aW11bSkpLA0KICAgICAgICAgICAgICAgICAgICAgICAgICBhbmd1bGFyYXhpcz1saXN0KHRoZXRhdW5pdD0ncmFkaWFucycsIGRpcmVjdGlvbj0iY2xvY2t3aXNlIiwgcm90YXRpb249MCkpLCANCiAgICAgICAgICAgICAgIHRpdGxlPXBsb3RfdGl0bGUsIGxlZ2VuZD1saXN0KG9yaWVudGF0aW9uPSJoIiwgeGFuY2hvcj0iY2VudGVyIiwgeD0wLjUpKQ0KICAgICAgU3lzLnNsZWVwKDApDQogICAgICBwcmludChwKQ0KICAgIH1lbHNlIGlmIChleGlzdHMoInNpZ19kaWZmMyIpKXsNCiAgICAgIHA9cGxvdF9seSh0eXBlPSdzY2F0dGVycG9sYXInLCBtb2RlPSdsaW5lcycpICU+JSANCiAgICAgICAgYWRkX3RyYWNlKHRoZXRhPXAxJGZ2JHRoZXRhX3VuY3V0X3oqMTgwL3BpLCByPXAxJGZ2JGZpdCwgbGluZT1saXN0KGNvbG9yPSJibHVlIiwgd2lkdGg9Mi41KSwgbmFtZT1uYW1lc19zbW9vdGhzWzFdKSAlPiUgDQogICAgICAgIGFkZF90cmFjZSh0aGV0YT1wMSRmdiR0aGV0YV91bmN1dF96KjE4MC9waSwgcj1wMSRmdiR1bCwgbGluZT1saXN0KGNvbG9yPSJibHVlIiwgZGFzaD0iZG90Iiwgd2lkdGg9MC41KSwgc2hvd2xlZ2VuZD1GQUxTRSkgJT4lIA0KICAgICAgICBhZGRfdHJhY2UodGhldGE9cDEkZnYkdGhldGFfdW5jdXRfeioxODAvcGksIHI9cDEkZnYkbGwsIGxpbmU9bGlzdChjb2xvcj0iYmx1ZSIsIGRhc2g9ImRvdCIsIHdpZHRoPTAuNSksIHNob3dsZWdlbmQ9RkFMU0UpICU+JSANCiAgICAgICAgYWRkX3RyYWNlKHRoZXRhPXAyJGZ2JHRoZXRhX3VuY3V0X3oqMTgwL3BpLCByPXAyJGZ2JGZpdCwgbGluZT1saXN0KGNvbG9yPSJyZWQiLCB3aWR0aD0yLjUpLCBuYW1lPW5hbWVzX3Ntb290aHNbMl0pICU+JSANCiAgICAgICAgYWRkX3RyYWNlKHRoZXRhPXAyJGZ2JHRoZXRhX3VuY3V0X3oqMTgwL3BpLCByPXAyJGZ2JHVsLCBsaW5lPWxpc3QoY29sb3I9InJlZCIsIGRhc2g9ImRvdCIsIHdpZHRoPTAuNSksIHNob3dsZWdlbmQ9RkFMU0UpICU+JSANCiAgICAgICAgYWRkX3RyYWNlKHRoZXRhPXAyJGZ2JHRoZXRhX3VuY3V0X3oqMTgwL3BpLCByPXAyJGZ2JGxsLCBsaW5lPWxpc3QoY29sb3I9InJlZCIsIGRhc2g9ImRvdCIsIHdpZHRoPTAuNSksIHNob3dsZWdlbmQ9RkFMU0UpICU+JQ0KICAgICAgICBhZGRfdHJhY2UodGhldGE9c2VxKHNpZ19kaWZmMVsxXSoxODAvcGksIHNpZ19kaWZmMVsyXSoxODAvcGksIGxlbmd0aC5vdXQ9MjApLCANCiAgICAgICAgICAgICAgICAgIHI9YygwLCByZXAobWF4aW11bSwgMTgpLCAwKSwgbGluZT1saXN0KGNvbG9yPSJibGFjayIsIHdpZHRoPTAuNSksIGZpbGw9InRvc2VsZiIsIGZpbGxjb2xvcj1yZ2IoMCwwLDAsbWF4PTI1NSxhbHBoYT0yNSksIHNob3dsZWdlbmQ9RkFMU0UpICU+JQ0KICAgICAgICBhZGRfdHJhY2UodGhldGE9c2VxKHNpZ19kaWZmMlsxXSoxODAvcGksIHNpZ19kaWZmMlsyXSoxODAvcGksIGxlbmd0aC5vdXQ9MjApLCANCiAgICAgICAgICAgICAgICAgIHI9YygwLCByZXAobWF4aW11bSwgMTgpLCAwKSwgbGluZT1saXN0KGNvbG9yPSJibGFjayIsIHdpZHRoPTAuNSksIGZpbGw9InRvc2VsZiIsIGZpbGxjb2xvcj1yZ2IoMCwwLDAsbWF4PTI1NSxhbHBoYT0yNSksIHNob3dsZWdlbmQ9RkFMU0UpICU+JQ0KICAgICAgICBhZGRfdHJhY2UodGhldGE9c2VxKHNpZ19kaWZmM1sxXSoxODAvcGksIHNpZ19kaWZmM1syXSoxODAvcGksIGxlbmd0aC5vdXQ9MjApLCANCiAgICAgICAgICAgICAgICAgIHI9YygwLCByZXAobWF4aW11bSwgMTgpLCAwKSwgbGluZT1saXN0KGNvbG9yPSJibGFjayIsIHdpZHRoPTAuNSksIGZpbGw9InRvc2VsZiIsIGZpbGxjb2xvcj1yZ2IoMCwwLDAsbWF4PTI1NSxhbHBoYT0yNSksIHNob3dsZWdlbmQ9RkFMU0UpICU+JQ0KICAgICAgICBsYXlvdXQocG9sYXI9bGlzdChzZWN0b3I9YygyMCwxNjApLCByYWRpYWxheGlzPWxpc3QoYW5nbGU9OTAsIHJhbmdlPWMoMCxtYXhpbXVtKSksDQogICAgICAgICAgICAgICAgICAgICAgICAgIGFuZ3VsYXJheGlzPWxpc3QodGhldGF1bml0PSdyYWRpYW5zJywgZGlyZWN0aW9uPSJjbG9ja3dpc2UiLCByb3RhdGlvbj0wKSksIA0KICAgICAgICAgICAgICAgdGl0bGU9cGxvdF90aXRsZSwgbGVnZW5kPWxpc3Qob3JpZW50YXRpb249ImgiLCB4YW5jaG9yPSJjZW50ZXIiLCB4PTAuNSkpDQogICAgICBTeXMuc2xlZXAoMCkNCiAgICAgIHByaW50KHApDQogICAgfWVsc2UgaWYgKGV4aXN0cygic2lnX2RpZmYyIikpew0KICAgICAgcD1wbG90X2x5KHR5cGU9J3NjYXR0ZXJwb2xhcicsIG1vZGU9J2xpbmVzJykgJT4lIA0KICAgICAgICBhZGRfdHJhY2UodGhldGE9cDEkZnYkdGhldGFfdW5jdXRfeioxODAvcGksIHI9cDEkZnYkZml0LCBsaW5lPWxpc3QoY29sb3I9ImJsdWUiLCB3aWR0aD0yLjUpLCBuYW1lPW5hbWVzX3Ntb290aHNbMV0pICU+JSANCiAgICAgICAgYWRkX3RyYWNlKHRoZXRhPXAxJGZ2JHRoZXRhX3VuY3V0X3oqMTgwL3BpLCByPXAxJGZ2JHVsLCBsaW5lPWxpc3QoY29sb3I9ImJsdWUiLCBkYXNoPSJkb3QiLCB3aWR0aD0wLjUpLCBzaG93bGVnZW5kPUZBTFNFKSAlPiUgDQogICAgICAgIGFkZF90cmFjZSh0aGV0YT1wMSRmdiR0aGV0YV91bmN1dF96KjE4MC9waSwgcj1wMSRmdiRsbCwgbGluZT1saXN0KGNvbG9yPSJibHVlIiwgZGFzaD0iZG90Iiwgd2lkdGg9MC41KSwgc2hvd2xlZ2VuZD1GQUxTRSkgJT4lIA0KICAgICAgICBhZGRfdHJhY2UodGhldGE9cDIkZnYkdGhldGFfdW5jdXRfeioxODAvcGksIHI9cDIkZnYkZml0LCBsaW5lPWxpc3QoY29sb3I9InJlZCIsIHdpZHRoPTIuNSksIG5hbWU9bmFtZXNfc21vb3Roc1syXSkgJT4lIA0KICAgICAgICBhZGRfdHJhY2UodGhldGE9cDIkZnYkdGhldGFfdW5jdXRfeioxODAvcGksIHI9cDIkZnYkdWwsIGxpbmU9bGlzdChjb2xvcj0icmVkIiwgZGFzaD0iZG90Iiwgd2lkdGg9MC41KSwgc2hvd2xlZ2VuZD1GQUxTRSkgJT4lIA0KICAgICAgICBhZGRfdHJhY2UodGhldGE9cDIkZnYkdGhldGFfdW5jdXRfeioxODAvcGksIHI9cDIkZnYkbGwsIGxpbmU9bGlzdChjb2xvcj0icmVkIiwgZGFzaD0iZG90Iiwgd2lkdGg9MC41KSwgc2hvd2xlZ2VuZD1GQUxTRSkgJT4lDQogICAgICAgIGFkZF90cmFjZSh0aGV0YT1zZXEoc2lnX2RpZmYxWzFdKjE4MC9waSwgc2lnX2RpZmYxWzJdKjE4MC9waSwgbGVuZ3RoLm91dD0yMCksIA0KICAgICAgICAgICAgICAgICAgcj1jKDAsIHJlcChtYXhpbXVtLCAxOCksIDApLCBsaW5lPWxpc3QoY29sb3I9ImJsYWNrIiwgd2lkdGg9MC41KSwgZmlsbD0idG9zZWxmIiwgZmlsbGNvbG9yPXJnYigwLDAsMCxtYXg9MjU1LGFscGhhPTI1KSwgc2hvd2xlZ2VuZD1GQUxTRSkgJT4lDQogICAgICAgIGFkZF90cmFjZSh0aGV0YT1zZXEoc2lnX2RpZmYyWzFdKjE4MC9waSwgc2lnX2RpZmYyWzJdKjE4MC9waSwgbGVuZ3RoLm91dD0yMCksIA0KICAgICAgICAgICAgICAgICAgcj1jKDAsIHJlcChtYXhpbXVtLCAxOCksIDApLCBsaW5lPWxpc3QoY29sb3I9ImJsYWNrIiwgd2lkdGg9MC41KSwgZmlsbD0idG9zZWxmIiwgZmlsbGNvbG9yPXJnYigwLDAsMCxtYXg9MjU1LGFscGhhPTI1KSwgc2hvd2xlZ2VuZD1GQUxTRSkgJT4lDQogICAgICAgIGxheW91dChwb2xhcj1saXN0KHNlY3Rvcj1jKDIwLDE2MCksIHJhZGlhbGF4aXM9bGlzdChhbmdsZT05MCwgcmFuZ2U9YygwLG1heGltdW0pKSwNCiAgICAgICAgICAgICAgICAgICAgICAgICAgYW5ndWxhcmF4aXM9bGlzdCh0aGV0YXVuaXQ9J3JhZGlhbnMnLCBkaXJlY3Rpb249ImNsb2Nrd2lzZSIsIHJvdGF0aW9uPTApKSwgDQogICAgICAgICAgICAgICB0aXRsZT1wbG90X3RpdGxlLCBsZWdlbmQ9bGlzdChvcmllbnRhdGlvbj0iaCIsIHhhbmNob3I9ImNlbnRlciIsIHg9MC41KSkNCiAgICAgIFN5cy5zbGVlcCgwKQ0KICAgICAgcHJpbnQocCkNCiAgICB9ZWxzZXsNCiAgICAgIHA9cGxvdF9seSh0eXBlPSdzY2F0dGVycG9sYXInLCBtb2RlPSdsaW5lcycpICU+JSANCiAgICAgICAgYWRkX3RyYWNlKHRoZXRhPXAxJGZ2JHRoZXRhX3VuY3V0X3oqMTgwL3BpLCByPXAxJGZ2JGZpdCwgbGluZT1saXN0KGNvbG9yPSJibHVlIiwgd2lkdGg9Mi41KSwgbmFtZT1uYW1lc19zbW9vdGhzWzFdKSAlPiUgDQogICAgICAgIGFkZF90cmFjZSh0aGV0YT1wMSRmdiR0aGV0YV91bmN1dF96KjE4MC9waSwgcj1wMSRmdiR1bCwgbGluZT1saXN0KGNvbG9yPSJibHVlIiwgZGFzaD0iZG90Iiwgd2lkdGg9MC41KSwgc2hvd2xlZ2VuZD1GQUxTRSkgJT4lIA0KICAgICAgICBhZGRfdHJhY2UodGhldGE9cDEkZnYkdGhldGFfdW5jdXRfeioxODAvcGksIHI9cDEkZnYkbGwsIGxpbmU9bGlzdChjb2xvcj0iYmx1ZSIsIGRhc2g9ImRvdCIsIHdpZHRoPTAuNSksIHNob3dsZWdlbmQ9RkFMU0UpICU+JSANCiAgICAgICAgYWRkX3RyYWNlKHRoZXRhPXAyJGZ2JHRoZXRhX3VuY3V0X3oqMTgwL3BpLCByPXAyJGZ2JGZpdCwgbGluZT1saXN0KGNvbG9yPSJyZWQiLCB3aWR0aD0yLjUpLCBuYW1lPW5hbWVzX3Ntb290aHNbMl0pICU+JSANCiAgICAgICAgYWRkX3RyYWNlKHRoZXRhPXAyJGZ2JHRoZXRhX3VuY3V0X3oqMTgwL3BpLCByPXAyJGZ2JHVsLCBsaW5lPWxpc3QoY29sb3I9InJlZCIsIGRhc2g9ImRvdCIsIHdpZHRoPTAuNSksIHNob3dsZWdlbmQ9RkFMU0UpICU+JSANCiAgICAgICAgYWRkX3RyYWNlKHRoZXRhPXAyJGZ2JHRoZXRhX3VuY3V0X3oqMTgwL3BpLCByPXAyJGZ2JGxsLCBsaW5lPWxpc3QoY29sb3I9InJlZCIsIGRhc2g9ImRvdCIsIHdpZHRoPTAuNSksIHNob3dsZWdlbmQ9RkFMU0UpICU+JQ0KICAgICAgICBhZGRfdHJhY2UodGhldGE9c2VxKHNpZ19kaWZmMVsxXSoxODAvcGksIHNpZ19kaWZmMVsyXSoxODAvcGksIGxlbmd0aC5vdXQ9MjApLCANCiAgICAgICAgICAgICAgICAgIHI9YygwLCByZXAobWF4aW11bSwgMTgpLCAwKSwgbGluZT1saXN0KGNvbG9yPSJibGFjayIsIHdpZHRoPTAuNSksIGZpbGw9InRvc2VsZiIsIGZpbGxjb2xvcj1yZ2IoMCwwLDAsbWF4PTI1NSxhbHBoYT0yNSksIHNob3dsZWdlbmQ9RkFMU0UpICU+JQ0KICAgICAgICBsYXlvdXQocG9sYXI9bGlzdChzZWN0b3I9YygyMCwxNjApLCByYWRpYWxheGlzPWxpc3QoYW5nbGU9OTAsIHJhbmdlPWMoMCxtYXhpbXVtKSksDQogICAgICAgICAgICAgICAgICAgICAgICAgIGFuZ3VsYXJheGlzPWxpc3QodGhldGF1bml0PSdyYWRpYW5zJywgZGlyZWN0aW9uPSJjbG9ja3dpc2UiLCByb3RhdGlvbj0wKSksIA0KICAgICAgICAgICAgICAgdGl0bGU9cGxvdF90aXRsZSwgbGVnZW5kPWxpc3Qob3JpZW50YXRpb249ImgiLCB4YW5jaG9yPSJjZW50ZXIiLCB4PTAuNSkpDQogICAgICBTeXMuc2xlZXAoMCkNCiAgICAgIHByaW50KHApDQogICAgfQ0KICB9DQp9DQpgYGANCg0KDQoNCiMgbG9hZCBpbiBkYXRhDQoNCmBgYHtyIHdhcm5pbmc9RkFMU0UsIG1lc3NhZ2U9RkFMU0UsIGVycm9yPUZBTFNFfQ0KZGYgPC0gcmVhZC5jc3YoImFsbF9kYXRhX05aRV9Ub25nYW5fd19jb250ZXh0X2NoZWNrZWRfN19NYXJjaF8yMDE5X25vdF9jdXRfY2hlY2tlZF8yN19BcHIuY3N2Iiwgc2VwPScsJywgc3RyaW5nc0FzRmFjdG9ycyA9IEYpDQoNCiMgcmVtb3ZlIGVtcHR5IGNvbHVtbg0KZGYkWCA9IE5VTEwNCg0KZGYkdG9rZW5Qb29sZWQgPC0gZmFjdG9yKGRmJHRva2VuUG9vbGVkKQ0KZGYkc3ViamVjdCA8LSBmYWN0b3IoZGYkc3ViamVjdCkNCmRmJHNleCA8LSBmYWN0b3IoZGYkc2V4KQ0KZGYkbmF0aXZlX2xnIDwtIGZhY3RvcihkZiRuYXRpdmVfbGcpDQoNCiMgdXBkYXRlZCANCmRmJHBsYXlpbmdfcHJvZmljaWVuY3lbZGYkcGxheWluZ19wcm9maWNpZW5jeSA9PSAiaW50ZXJtZWRpYXRlIl0gPC0gImFtYXRldXIiDQpkZiRwbGF5aW5nX3Byb2ZpY2llbmN5IDwtIGZhY3RvcihkZiRwbGF5aW5nX3Byb2ZpY2llbmN5LCBsZXZlbHMgPSBjKCJhbWF0ZXVyIiwic2VtaS1wcm9mZXNzaW9uYWwiLCJwcm9mZXNzaW9uYWwiKSkNCg0KZGYkYmxvY2sgPC0gZmFjdG9yKGRmJGJsb2NrKQ0KZGYkdGhldGFfdW5jdXRfeiA8LSBhcy5udW1lcmljKGRmJHRoZXRhX3VuY3V0X3opDQoNCiMgdXBkYXRlZA0KZGYkbm90ZV9pbnRlbnNpdHkgPC0gZmFjdG9yKGRmJG5vdGVfaW50ZW5zaXR5LCBsZXZlbHMgPSBjKCJwaWFubyIsIm1lenpvcGlhbm8iLCJtZXp6b2ZvcnRlIiwiZm9ydGUiKSkNCg0KZGYkdG9rZW5Qb29sZWQgPC0gZmFjdG9yKGRmJHRva2VuUG9vbGVkKQ0KDQpgYGANCg0KIyBwcmVkaWN0IGF2ZXJhZ2UgdmFsdWVzIGZvciBub3RlIHByb2R1Y3Rpb25zIE5aRSB2cyBUb25nYW4NCg0KIyMgRGF0YSBtYW5pcHVsYXRpb24NCg0KYGBge3Igd2FybmluZz1GQUxTRSwgbWVzc2FnZT1GQUxTRSwgZXJyb3I9RkFMU0V9DQpkZlN1bW1hcnkgPC0gZ3JvdXBfYnkoZGYsIHN1YmplY3QsIHBsYXlpbmdfcHJvZmljaWVuY3ksIGFjdGl2aXR5LCBuYXRpdmVfbGcsIHRva2VuUG9vbGVkLCB0aGV0YV91bmN1dF96X2dyb3VwID0gY3V0KHRoZXRhX3VuY3V0X3osYnJlYWtzPTEwMCkpICU+JSBzdW1tYXJpc2UocmhvVmFyID0gc2QocmhvX3VuY3V0X3osbmEucm09VFJVRSkpDQoNCg0KZGZTdW1tYXJ5JHRoZXRhX3VuY3V0X3ogPSBhcy5jaGFyYWN0ZXIoZGZTdW1tYXJ5JHRoZXRhX3VuY3V0X3pfZ3JvdXApDQoNCmRmU3VtbWFyeSR0aGV0YV91bmN1dF96ID0gZ3N1YigiXFxbfFxcXXxcXCh8XFwpIiwgIiIsZGZTdW1tYXJ5JHRoZXRhX3VuY3V0X3opDQoNCmRmU3VtbWFyeSR0aGV0YV91bmN1dF96ID0gc3Ryc3BsaXQoZGZTdW1tYXJ5JHRoZXRhX3VuY3V0X3osIiwiKQ0KDQpkZlN1bW1hcnkkdGhldGFfdW5jdXRfejIgPSAxDQpmb3IoaSBpbiBjKDE6bnJvdyhkZlN1bW1hcnkpKSkNCnsNCiAgZGZTdW1tYXJ5JHRoZXRhX3VuY3V0X3oyW2ldID0gbWVhbihhcy5udW1lcmljKHVubGlzdChkZlN1bW1hcnkkdGhldGFfdW5jdXRfeltpXSkpKQ0KfQ0KDQpkZlN1bW1hcnkkdGhldGFfdW5jdXRfej1kZlN1bW1hcnkkdGhldGFfdW5jdXRfejINCg0KZGZTdW1tYXJ5JHBsYXlpbmdfcHJvZmljaWVuY3kub3JkIDwtIGFzLm9yZGVyZWQoZGZTdW1tYXJ5JHBsYXlpbmdfcHJvZmljaWVuY3kpDQpjb250cmFzdHMoZGZTdW1tYXJ5JHBsYXlpbmdfcHJvZmljaWVuY3kub3JkKSA8LSAiY29udHIudHJlYXRtZW50Ig0KDQpkZlN1bW1hcnkkYWN0aXZpdHkub3JkIDwtIGFzLm9yZGVyZWQoZGZTdW1tYXJ5JGFjdGl2aXR5KQ0KY29udHJhc3RzKGRmU3VtbWFyeSRhY3Rpdml0eS5vcmQpIDwtICJjb250ci50cmVhdG1lbnQiDQoNCmRmU3VtbWFyeSRsYW5nTm90ZUludCA8LSBpbnRlcmFjdGlvbihkZlN1bW1hcnkkbmF0aXZlX2xnLCANCmRmU3VtbWFyeSR0b2tlblBvb2xlZCkNCg0KZGZTdW1tYXJ5JGxhbmdOb3RlSW50Lm9yZCA8LSBhcy5vcmRlcmVkKGRmU3VtbWFyeSRsYW5nTm90ZUludCkNCmNvbnRyYXN0cyhkZlN1bW1hcnkkbGFuZ05vdGVJbnQub3JkKSA8LSAiY29udHIudHJlYXRtZW50Ig0KDQpkZlN1bW1hcnkkbmF0aXZlX2xnLm9yZCA8LSBhcy5vcmRlcmVkKGRmU3VtbWFyeSRuYXRpdmVfbGcpDQpjb250cmFzdHMoZGZTdW1tYXJ5JG5hdGl2ZV9sZy5vcmQpIDwtICJjb250ci50cmVhdG1lbnQiDQoNCmRmU3VtbWFyeSR0b2tlblBvb2xlZC5vcmQgPC0gYXMub3JkZXJlZChkZlN1bW1hcnkkdG9rZW5Qb29sZWQpDQpjb250cmFzdHMoZGZTdW1tYXJ5JHRva2VuUG9vbGVkLm9yZCkgPC0gImNvbnRyLnRyZWF0bWVudCINCg0KZGZTdW1tYXJ5ID0gbmEub21pdChkZlN1bW1hcnkpDQoNCg0KZm9yKGkgaW4gdW5pcXVlKGRmU3VtbWFyeSRzdWJqZWN0KSkNCnsNCiAgZGZTdWJqZWN0ID0gc3Vic2V0KGRmU3VtbWFyeSxkZlN1bW1hcnkkc3ViamVjdCA9PSBpKQ0KICBmb3IoaiBpbiB1bmlxdWUoZGZTdWJqZWN0JHRva2VuUG9vbGVkKSkNCiAgew0KICAgIGRmU3VtbWFyeSRzdGFydFtkZlN1bW1hcnkkc3ViamVjdCA9PSBpICYgZGZTdW1tYXJ5JHRva2VuUG9vbGVkID09IGpdIDwtIA0KICAgICAgZGZTdW1tYXJ5JHRoZXRhX3VuY3V0X3pbZGZTdW1tYXJ5JHN1YmplY3QgPT0gaSAmIGRmU3VtbWFyeSR0b2tlblBvb2xlZCA9PSBqXSA9PQ0KICAgICAgbWluKGRmU3VtbWFyeSR0aGV0YV91bmN1dF96W2RmU3VtbWFyeSRzdWJqZWN0ID09IGkgJiBkZlN1bW1hcnkkdG9rZW5Qb29sZWQgPT0gal0pDQogIH0NCn0NCg0KYGBgDQoNCiMjIE1vZGVsIHNwZWNpZmljYXRpb24NCg0KYGBge3Igd2FybmluZz1GQUxTRSwgbWVzc2FnZT1GQUxTRSwgZXJyb3I9RkFMU0V9DQppZiAocnVuX21vZGVscyA9PSBUUlVFKXsNCiAgbWRsLnN5cy50aW1lMSA8LSBzeXN0ZW0udGltZShWQVIuZ2FtLm5vQVIuTW9kMSA8LSBiYW0ocmhvVmFyIH4gbGFuZ05vdGVJbnQub3JkICsgcyh0aGV0YV91bmN1dF96LCBicz0iY3IiLCBrPTEwKSArIHModGhldGFfdW5jdXRfeiwgYnM9ImNyIiwgaz0xMCwgYnk9bGFuZ05vdGVJbnQub3JkKSArcyh0aGV0YV91bmN1dF96LCBzdWJqZWN0LCBicz0iZnMiLCBrPTEwLCBtPTEsIGJ5PWxhbmdOb3RlSW50Lm9yZCksIGRhdGE9ZGZTdW1tYXJ5LCBkaXNjcmV0ZT1UUlVFLCBudGhyZWFkcz1uY29yZXMsIG1ldGhvZCA9ICJmUkVNTCIpKQ0KICAgbWRsLnN5cy50aW1lMQ0KICAgIyBzYXZlIG1vZGVsICYgbW9kZWwgc3VtbWFyeSBzbyB0aGV5IGNhbiBiZSByZWxvYWRlZCBsYXRlcg0KICAgc2F2ZVJEUyhWQVIuZ2FtLm5vQVIuTW9kMSwgcGFzdGUwKG91dHB1dF9kaXIsIi9WQVIuZ2FtLm5vQVIuTW9kMS5yZHMiKSkNCiAgIGNhcHR1cmUub3V0cHV0KHN1bW1hcnkoVkFSLmdhbS5ub0FSLk1vZDEpLCANCiAgICAgICAgICAgICAgICAgIGZpbGUgPSBwYXN0ZTAob3V0cHV0X2RpciwiL3N1bW1hcnlfVkFSLmdhbS5ub0FSLk1vZDEudHh0IikpDQp9ZWxzZXsNCiAgIyByZWxvYWQgbW9kZWwgZnJvbSBvdXRwdXRfZGlyDQogIFZBUi5nYW0ubm9BUi5Nb2QxID0gcmVhZFJEUyhwYXN0ZTAob3V0cHV0X2RpciwiL1ZBUi5nYW0ubm9BUi5Nb2QxLnJkcyIpKQ0KfQ0KDQppZiAocnVuX21vZGVscyA9PSBUUlVFKXsNCiAgIyBzZXQgc3RhcnRfdmFsdWVfcmhvIGZyb20gVkFSLmdhbS5ub0FSLk1vZDEgYXMgcmhvX2VzdCBmb3IgdGhlIG5leHQgbW9kZWwNCiAgcmhvX2VzdCA8LSBzdGFydF92YWx1ZV9yaG8oVkFSLmdhbS5ub0FSLk1vZDEpDQogIG1kbC5zeXMudGltZTIgPC0gc3lzdGVtLnRpbWUoVkFSLmdhbS5BUi5Nb2QyIDwtIGJhbShyaG9WYXIgfiBsYW5nTm90ZUludC5vcmQgKyBzKHRoZXRhX3VuY3V0X3osIGJzPSJjciIsIGs9MTApICsgcyh0aGV0YV91bmN1dF96LCBicz0iY3IiLCBrPTEwLCBieT1sYW5nTm90ZUludC5vcmQpICsgIHModGhldGFfdW5jdXRfeiwgc3ViamVjdCwgYnM9ImZzIiwgaz0xMCwgbT0xLCBieT1sYW5nTm90ZUludC5vcmQpLCBBUi5zdGFydD1kZlN1bW1hcnkkc3RhcnQsIHJobz1yaG9fZXN0LCBkYXRhPWRmU3VtbWFyeSwgZGlzY3JldGU9VFJVRSwgbnRocmVhZHM9bmNvcmVzLCBtZXRob2QgPSAiZlJFTUwiKSkNCiAgbWRsLnN5cy50aW1lMg0KICAjIHNhdmUgbW9kZWwgJiBtb2RlbCBzdW1tYXJ5IHNvIHRoZXkgY2FuIGJlIHJlbG9hZGVkIGxhdGVyDQogIHNhdmVSRFMoVkFSLmdhbS5BUi5Nb2QyLCBwYXN0ZTAob3V0cHV0X2RpciwiL1ZBUi5nYW0uQVIuTW9kMi5yZHMiKSkNCiAgY2FwdHVyZS5vdXRwdXQoc3VtbWFyeShWQVIuZ2FtLkFSLk1vZDIpLCANCiAgICAgICAgICAgICAgICAgZmlsZSA9IHBhc3RlMChvdXRwdXRfZGlyLCIvc3VtbWFyeV9WQVIuZ2FtLkFSLk1vZDIudHh0IikpDQp9ZWxzZXsNCiAgIyByZWxvYWQgbW9kZWwgZnJvbSBvdXRwdXRfZGlyDQogIFZBUi5nYW0uQVIuTW9kMiA9IHJlYWRSRFMocGFzdGUwKG91dHB1dF9kaXIsIi9WQVIuZ2FtLkFSLk1vZDIucmRzIikpDQp9DQpgYGANCg0KIyMgTW9kZWwgaW5zcGVjdGlvbg0KDQojIyMgQ2hlY2tpbmcgQUNGDQoNCiMjIyMgRnVsbA0KDQpgYGB7ciB3YXJuaW5nPUZBTFNFLCBtZXNzYWdlPUZBTFNFLCBlcnJvcj1GQUxTRX0NCmFjZl9yZXNpZChWQVIuZ2FtLkFSLk1vZDIsIG1haW4gPSAiQXZlcmFnZSBBQ0YgQVIiLCBjZXgubGFiPTEuNSwgY2V4LmF4aXM9MS41KQ0KYGBgDQoNCg0KIyMjIyBCeSBUb2tlbg0KDQpgYGB7ciB3YXJuaW5nPUZBTFNFLCBtZXNzYWdlPUZBTFNFLCBlcnJvcj1GQUxTRX0NCmFjZl9yZXNpZChWQVIuZ2FtLkFSLk1vZDIsc3BsaXRfcHJlZD1saXN0KGRmU3VtbWFyeSR0b2tlblBvb2xlZCksbWFpbiA9ICJBdmVyYWdlIEFDRiBBUiBieSB0b2tlblBvb2xlZCIsY2V4LmxhYj0xLjUsY2V4LmF4aXM9MS41KQ0KYGBgDQoNCiMjIyMgQnkgTGFuZ3VhZ2UNCg0KYGBge3Igd2FybmluZz1GQUxTRSwgbWVzc2FnZT1GQUxTRSwgZXJyb3I9RkFMU0V9DQphY2ZfcmVzaWQoVkFSLmdhbS5BUi5Nb2QyLHNwbGl0X3ByZWQ9bGlzdChkZlN1bW1hcnkkbmF0aXZlX2xnKSxtYWluID0gIkF2ZXJhZ2UgQUNGIEFSIGJ5IG5hdGl2ZSBsYW5ndWFnZSIsY2V4LmxhYj0xLjUsY2V4LmF4aXM9MS41KQ0KYGBgDQoNCg0KIyMjIFN1bW1hcnkgb2YgdGhlIG1vZGVsDQoNCmBgYHtyIHdhcm5pbmc9RkFMU0UsIG1lc3NhZ2U9RkFMU0UsIGVycm9yPUZBTFNFfQ0Kc3VtbWFyeShWQVIuZ2FtLkFSLk1vZDIpDQpgYGANCg0KIyMjIFBsb3R0aW5nIG1vZGVsIHByZWRpY3Rpb25zDQoNCiMjIyMgT3ZlcmFsbCB2YXJpYW5jZSBkaWZmZXJlbmNlcw0KDQpBbmQgZmluYWxseSBvdmVyYWxsIHZhcmlhbmNlIGRpZmZlcmVuY2VzIGJ5IGxhbmd1YWdlDQoNCmBgYHtyfQ0KIyBtYWtlIGNvcHkgb2YgZGZOb3Rlcw0KZGF0MSA9IGRmU3VtbWFyeQ0KZGF0MSRwcmVkaWN0ZWRfdmFsdWVzID0gcHJlZGljdChWQVIuZ2FtLkFSLk1vZDIpDQoNCiMgcGxvdCBpbiBwb2xhciBjb29yZGluYXRlcyB1c2luZyBwbG90bHkNCmRhdDFfTlpFID0gZGF0MVtkYXQxJG5hdGl2ZV9sZyA9PSAiTlpFIixdDQpkYXQxX1RvbmdhbiA9IGRhdDFbZGF0MSRuYXRpdmVfbGcgPT0gIlRvbmdhbiIsXQ0KDQojIGVzdGltYXRlIHNtb290aHMgdXNpbmcgUidzIGdlbmVyaWMgcHJlZGljdC5zbW9vdGguc3BsaW5lIGZ1bmN0aW9uDQpzbW9vdGhfTlpFPWxpc3QodGhldGE9c2VxKG1pbihkYXQxX05aRSR0aGV0YV91bmN1dF96KSoxODAvcGksIG1heChkYXQxX05aRSR0aGV0YV91bmN1dF96KSoxODAvcGksIGxlbmd0aD0xMDApLCByPXByZWRpY3Qoc21vb3RoLnNwbGluZShkYXQxX05aRSR0aGV0YV91bmN1dF96LCBkYXQxX05aRSRwcmVkaWN0ZWRfdmFsdWVzKSwNCiBzZXEobWluKGRhdDFfTlpFJHRoZXRhX3VuY3V0X3opLCBtYXgoZGF0MV9OWkUkdGhldGFfdW5jdXRfeiksIGxlbmd0aD0xMDApKSR5LCBsaW5lPWxpc3QoY29sb3I9ImJsdWUiLCBkYXNoPSJkYXNoIikpDQoNCnNtb290aF9Ub25nYW49bGlzdCh0aGV0YT1zZXEobWluKGRhdDFfVG9uZ2FuJHRoZXRhX3VuY3V0X3opKjE4MC9waSwgbWF4KGRhdDFfVG9uZ2FuJHRoZXRhX3VuY3V0X3opKjE4MC9waSwgbGVuZ3RoPTEwMCksIHI9cHJlZGljdChzbW9vdGguc3BsaW5lKGRhdDFfVG9uZ2FuJHRoZXRhX3VuY3V0X3osIGRhdDFfVG9uZ2FuJHByZWRpY3RlZF92YWx1ZXMpLA0KIHNlcShtaW4oZGF0MV9Ub25nYW4kdGhldGFfdW5jdXRfeiksIG1heChkYXQxX1RvbmdhbiR0aGV0YV91bmN1dF96KSwgbGVuZ3RoPTEwMCkpJHksIGxpbmU9bGlzdChjb2xvcj0icmVkIiwgZGFzaD0iIikpDQoNCiMgc2V0IFJobyBtYXggdG8gdGhlIG1heCBvZiB0aGUgcHJlZGljdGVkX3ZhbHVlcyArIDUNCm1heF9wcmVkaWN0aW9ucyA9IG1heChtYXgoc21vb3RoX05aRSRyKSwgbWF4KHNtb290aF9Ub25nYW4kcikpDQptYXhpbXVtPW1heF9wcmVkaWN0aW9ucys1DQpybShtYXhfcHJlZGljdGlvbnMpDQoNCnAgPSBwbG90X2x5KHR5cGU9J3NjYXR0ZXJwb2xhcicsIG1vZGU9J2xpbmVzJykgJT4lDQphZGRfdHJhY2UodGhldGE9c21vb3RoX05aRSR0aGV0YSwgcj1zbW9vdGhfTlpFJHIsIGxpbmU9bGlzdChjb2xvcj1zbW9vdGhfTlpFJGxpbmUkY29sb3JbWzFdXSwgd2lkdGg9Mi41LCBkYXNoPXNtb290aF9OWkUkbGluZSRkYXNoW1sxXV0pLCBuYW1lPSJvdmVyYWxsIGF2ZXJhZ2Ugb2YgTlpFIG5vdGVzIikgJT4lDQogIGFkZF90cmFjZSh0aGV0YT1zbW9vdGhfVG9uZ2FuJHRoZXRhLCByPXNtb290aF9Ub25nYW4kciwgbGluZT1saXN0KGNvbG9yPXNtb290aF9Ub25nYW4kbGluZSRjb2xvcltbMV1dLCB3aWR0aD0yLjUsIGRhc2g9c21vb3RoX1RvbmdhbiRsaW5lJGRhc2hbWzFdXSksIG5hbWU9Im92ZXJhbGwgYXZlcmFnZSBvZiBUb25nYW4gbm90ZXMiKSAlPiUNCiAgbGF5b3V0KHBvbGFyPWxpc3Qoc2VjdG9yPWMoMjAsMTYwKSwgcmFkaWFsYXhpcz1saXN0KGFuZ2xlPTkwLCByYW5nZT1jKDAsbWF4aW11bSkpLCBhbmd1bGFyYXhpcz1saXN0KHRoZXRhdW5pdD0ncmFkaWFucycsIGRpcmVjdGlvbj0iY2xvY2t3aXNlIiwgcm90YXRpb249MCkpLCB0aXRsZT0iT3ZlcmFsbCBhdmVyYWdlIHNtb290aHMgZm9yIE5aRSB2cyBUb25nYW4gbm90ZSBwcm9kdWN0aW9ucyIsIGxlZ2VuZD1saXN0KG9yaWVudGF0aW9uPSJoIiwgeGFuY2hvcj0iY2VudGVyIiwgeD0wLjUpKQ0KcA0KDQpybShkYXQxLCBkYXQxX05aRSwgZGF0MV9Ub25nYW4sIG1heGltdW0sIHNtb290aF9OWkUsIHNtb290aF9Ub25nYW4pDQpgYGANCg0KIA0KDQo=